Always a bad sign in code. Not least in security code. But the security holes
began far earlier in the boot process.
The device contains an OMAP 4470 and is not supported by Android’s most common
bootloader, ‘Little Kernel’. Instead, they chose to use 'Das U-Boot’ which,
thankfully, is GPL licensed so they were forced to release the code. This is the
verification code from the bootloader
There is a huge gaping hole in this code.
So… you’re going to use the certificate, which hasn’t even been verified yet,
to find out how much to read and, in turn, verify that certificate? Um… OK?
So that’s bad. But surely they put checks in? Apparently not. So they used
untrusted input to verify that same untrusted input. Right…
It can’t be that bad, can it? It’s not like they set up the stack a few
megabytes after the address they read the boot image to? Wait a minute, they did
exactly that. If they hadn’t set up the stack there, the exploit may have been
far more complicated, but this makes it child’s play.
This is basically a buffer overflow and the worst part is that the memory layout
at this stage in the boot process is totally predictable. If we can overwrite
the stack, we can jump anywhere we want, in this case to another bootloader
which will boot anything. In other words, we can force the bootloader to execute
Never use untrusted input unless absolutely necessary.
When you use a VCS, the amount of commands you use to do your work increases
greatly, the cost you pay for the many great features of a VCS.
But why? Surely we should be able to use a powerful VCS at no “cost”.
One way of improving your workflow is by aliasing commands. Commonly used
commands such as status or commit can be aliased to shorter commands.
Aliasing them to one-word commands (such as gcm for git commit -m) allows
your shell completion to take away most of the effort, requiring only one or two
characters to be pressed.
Don’t get me wrong, I like aliases and scripts. I even have one to run Jekyll
with my offline config; hell, I even have a ton for my editor and window manager
(vim and i3, if you wanted to know). Sometimes, though, you need to perform
a task automatically. Typing j<ENTER> to build my Jekyll blog isn’t good
enough. It should be built before I commit and a non-building blog should
NEVER be commited.
It should built before I commit
A commit is a “task” that could be “hooked”
and a non-building blog should NEVER be commited
It could check the exit value of this “hook”
Meet git hooks. In my opinion, most things should have hooks for as much as
possible, as long as it doesn’t bloat the software too much — in which case,
it needs a bit of rewriting. Some software which should, doesn’t
(pacman!). But most software should.
Simply put, hooks provide the functionality to react to something happening,
and, in some cases, modify the outcome. git provides us with many hooks, some
may be lacking but functionality can mostly be implemented with the ones
available to us, even if not optimal. Hooks live in hooks in the gitdir
(normally .git) and git even comes with some sample hooks
To find out more about git hooks, in general
But, for this blog, I only needed use two hooks, pre-commit
Fake trees inside real trees?
I used git-subtree for this blog.
Subtrees allow you to synthesise a history based on a subdirectory in another
history. IOW, it allows you to use a subdirectory as a new branch or repository,
even, whilst preserving its history. Unfortunately, you need to store generated
files in your “work” branch (or repository) but, it is a small price to pay as
git-subtree is more robust against rewriting history that the alternatives (as
it synthesises a new history everytime)
Putting it all together
It was simple. pre-commit should build the blog, add it to the index and only
finish the commit, if it passed. pre-push should point the master branch
(the published site) to the _site subfolder using a subtree then push it to
the remote (since push already knows which refs to push, we cannot change them
in pre-push). Note, we don’t want an infinite loop (pre-push => push =>
pre-push => push => etc…)
Why? I have a BT Home Hub, a memory stick and way too much free time!
NOTE: When configuring software using menuconfig it may be useful to know
that pressing / pulls up a search box for configuration options.
It works. Really? Yep.
Debian 8.1 and OpenWRT r46693 with SysVinit or systemd
Getting the OpenWRT source code
Start menuconfig and select the target
Load the defaults for the target
Start menuconfig again and configure the following options or append these to
.config and re-run make defconfig
For USB support
Populates /dev during early boot and a requirement of Debian
For ext4 support (change accordingly)
For U-Boot configuration
For systemd support (not required if using SysVinit)
Configuring the kernel
From menuconfig disable CONFIG_SOFT_FLOAT
Start make kernel_menuconfig and enable CONFIG_MIPS_FPU_EMULATOR
NOTE: When using kernel_menuconfig you may find options selected there
are ignored. Although kernel_menuconfig provides direct access to the kernel’s
config, options available in OpenWRT’s config (such as those in the previous
section) override those in the kernel’s config. At the time of writing, the MIPS
FPU emulator is not available as an OpenWRT config option.
The uImage kernel and initramfs can be found in bin/lantiq and the
ubinized images can be found in build_dir/target-*/linux-lantiq_xway. Make
sure to flash the ubifs image instead of the squashfs image as the overlay
is not mounted early enough in the boot process.
The simplest way to install Debian is to use debootstrap and
qemu-user-static then copy the folder to the USB drive. The USB drive should
be partitioned with swap and a partition of the chosen filesystem (in this case,
ext2). I partitoned mine with swap first (/dev/sda1) then rootfs after
To build the rootfs
On a systemd-based host, you can enter the rootfs using systemd-nspawn
Otherwise use chroot and mount the pseudo-filesystems
Once you are inside the rootfs, you can configure the system and install
packages. Make sure to setup the Ethernet switch and install and configure
To ensure systemd-udevd can access the modules, run
And enable the swap
Also, you could downgrade to SysVinit (tested, working) at this stage and a
useful trick would be to light the Power LED on boot (NOTE: there is a
Debian’s init must be run with PID 1. The boot process of OpenWRT is simple
We only modify /etc/preinit slightly (it sources /etc/debian_boot and
redirects the output to a debugging log on the NAND). We need to keep PID 1 but
don’t want to exec to /etc/debian_boot in case, for some reason, we can’t
boot Debian. Instead we source it so it runs in the same shell.
The anatomy of /etc/debian_boot is also very simple
mount /proc, /sys (/dev will be mounted by CONFIG_DEVTMPFS_MOUNT)
wait for USB drive
if found, mount and exec Debian’s init
else, do nothing (so we return to and continue /etc/preinit)
To inject our code into /etc/preinit we must find the line which corresponds
to step 3 in the OpenWRT boot process (shown above, in the first one)
This line should be the first line. Above this line we insert
This means it only runs the first time (when PID is 1) and logs stderr and
stdout to /debian.log on the NAND
When reading this script, remember that the output is logged (e.g. date is for
logging purposes only and won’t affect the bootup, ditto for the echos). This
script mounts /proc and /sys, loads required modules (jdb2 is a
dependency of ext4), waits on the USB for 5 seconds. If it is mounted and has
/sbin/init, the orange Upgrading LED is lit and it is pivoted into and
/sbin/init is execed. Otherwise, we umount our mountpoints (to ensure the
environment is as expected for OpenWRT) and fallthrough. Remember to change
$USB to your requirements.
I would prefer to use [ -x /debian/sbin/init ] but that won’t work in the case
of systemd when it is a symlink to /lib/systemd/systemd, a file that is
non-existent until we pivot_root. Sad face.
The script needn’t be marked executable and, to avoid mistakes, perhaps
shouldn’t. Also, some of the modules may be unnecessary (I’m looking at you,
ehci-hcd and ehci-platform) as there is a Lantiq-specific ltq_hcd_danube.
Can’t hurt, eh?
Before booting, check that you can mount the USB drive from OpenWRT.
This is the hardest part yet.
Troubleshooting — aka RTFL (the last one stands for logs)
If it boots into OpenWRT, then it couldn’t find the memory stick or /sbin/init
on it. Check you got $USB right, add some debugging into /etc/debian_boot
(such as ls /dev or df or mount — be creative!) For really slow memory
sticks, if the Upgrading LED fails to light, increase $WAIT to 10 or 15 then
hop on to Amazon and buy yourself a new one
If you followed this tutorial you have many many logs for you to read. Where?
Firstly there is /debian.log on the NAND if the Power LED fails to light
(after a REASONABLE amount of time — don’t be impatient!). Before unplugging
the USB drive, try pinging the router, it may be still booting!
If that doesn’t tell you anything, howsa about some of them Debian logs? You can
find them in /var/log and, if using systemd, you can find stuff in the
Finally, check if you got the configuration options correct for OpenWRT and the
kernel. Easy mistake to make!
Woot. Like I said, this is a blog.
And this is the second post. But the third. And the second. But it’s the third.
And this is a joke. And it’s really unfunny now…
Anyway… before I even wrote the first (which turned out to be the second)
post, there was much work to be done.
It took a day’s work to finally get up and running but I was proud of my self.
I chose Jekyll because I like DIY. I would have chosen Blogger or Wordpress if I
didn’t. But I do.
If I didn’t write plugins for it or write my own theme for it, it wouldn’t be
DIY? And, anyway, I had a vision of what my blog would look like before I made.
And my idea was just like this. And yes, that was a link to the current
page because, well, I believe I have achieved what I wanted.
If something works on IE6, that’s something to celebrate. But if something
just works on IE6, that’s a miracle. And no, works != just_works. Also,
no, I don’t like Microsoft. Apart from Outlook.com. And Office because I’m in
school and have been coerced forced into the Microsoft ecosystem.
I use a tiling window manager so my workflow is really
simple. I have a browser with the blog open on workspace 1. On workspace 2, I
have my terminal with Vim, the best editor, and — sometimes — a browser
open to look up stuff. Finally, I have jekyll serve running on the last
workspace (workspace 10), auto-generating my blog. Awesome.
I also write myself plugins for Liquid and Redcarpet,
the best Markdown rendering library. This makes blogging so much easier.
That’s the thing about Jekyll. It’s so customisable. And customisable ==
NOTE: I had absolutely no Ruby experience before starting this blog
NOTE: After finishing this post, I immediately proceeded to rewrite all the
SCSS as it was not clean enough for me