$ cat life > /dev/urandom

# Saleem Rashid

Cracking the Kindle Fire HD (3rd Generation)

Explanation on the method used to crack the Kindle Fire HD (3rd Generation)

TL;DR Unlock the bootloader and install TWRP here

New Year’s Resolution: 1080p Blog more.

Buffer overflow.

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

 1     /* load first fragment to determine image size thanks to the certificate  */
 2     if (mmc_read(mmcc, sector, addr, FIRST_FRAGMENT_SIZE_IN_BLOCKS*512) != 1) {
 3         printf("booti: mmc failed to read certificate\n");
 4         return -1;
 5     }
 6     addr   += FIRST_FRAGMENT_SIZE_IN_BLOCKS*512;
 9     /* Load image */
10         nb_bytes    = ISW_hash_struct_ptr->length + ISW_hash_struct_ptr->start_offset;
11         nb_bytes   -= FIRST_FRAGMENT_SIZE_IN_BLOCKS*512; // removed block which have been already loaded
13     if (mmc_read(mmcc, sector, addr, nb_bytes) != 1) {
14         printf("booti: failed to load image\n");
15         return -1;
16     }
18         return certificate_signature_verify((unsigned char*)load_addr);

There is a huge gaping hole in this code.

1     /* load first fragment to determine image size thanks to the certificate  */
2     if (mmc_read(mmcc, sector, addr, FIRST_FRAGMENT_SIZE_IN_BLOCKS*512) != 1) {

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?

1     /* Load image */
2         nb_bytes    = ISW_hash_struct_ptr->length + ISW_hash_struct_ptr->start_offset;
3         nb_bytes   -= FIRST_FRAGMENT_SIZE_IN_BLOCKS*512; // removed block which have been already loaded
5     if (mmc_read(mmcc, sector, addr, nb_bytes) != 1) {

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 unsigned code. :laughing:

Never use untrusted input unless absolutely necessary.

git hooks: Rigging the game

Improving your workflow with git hooks

NOTE: I don’t let GitHub build my blog as I use plugins that won’t work with Jekyll’s safe mode

If you aren’t using the best VCS of all time, install it. That of course assumes you are using the best distro of all time.

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”.

such cost. much overhead. very cry. wow.

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

1 ls .git/hooks/*.sample

To find out more about git hooks, in general

1 man githooks

But, for this blog, I only needed use two hooks, pre-commit and pre-push.

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)

1 man git-subtree

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…)

You can see the hooks in the repository for this blog.

Debian on a BT Home Hub

A comprehensive guide on installing Debian Jessie on the BT Home Hub 2.0 Type B

This is actually the second post? But it’s the first?

EDIT: Due to the new sorting mechanism, this is now the second post in the archives :confused:

Anyway… This tutorial shows you how to install Debian 8 on a BT Home Hub 2.0 Type B running OpenWRT. Access to the netconsole is assumed, as is experience with Debian and Linux, in general.

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

1 git clone git://git.openwrt.org/openwrt.git
2 cd openwrt
3 ./scripts/feeds update -a
4 ./scripts/feeds install -a

Configuring OpenWRT

Start menuconfig and select the target

1 CONFIG_TARGET_lantiq=y
2 CONFIG_TARGET_lantiq_xway=y

Load the defaults for the target

1 make defconfig

Start menuconfig again and configure the following options or append these to .config and re-run make defconfig

  • For USB support
2 CONFIG_PACKAGE_kmod-usb2=y
3 CONFIG_PACKAGE_kmod-usb-storage=y
4 CONFIG_PACKAGE_kmod-usb-storage-extras=y
  • Populates /dev during early boot and a requirement of Debian
  • For ext4 support (change accordingly)
1 CONFIG_PACKAGE_kmod-fs-ext4=y
  • For U-Boot configuration
1 CONFIG_PACKAGE_uboot-envtools=y
  • 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.

Building OpenWRT

1 make

Flashing OpenWRT

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 (/dev/sda2).

To build the rootfs

1 debootstrap --arch=mips --foreign jessie debian http://ftp.uk.debian.org/debian/
2 cp /usr/bin/qemu-mips-static debian/usr/bin
3 chroot debian /debootstrap/debootstrap --second-stage

On a systemd-based host, you can enter the rootfs using systemd-nspawn

1 systemd-nspawn -D debian -n

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 openssh-server

1 auto eth0
2 iface eth0 inet static
3     address
4     netmask

To ensure systemd-udevd can access the modules, run

1 ln -s ../openwrt/lib/modules /lib/

And enable the swap

1 # <file system>                 <mount point>   <type> <options> <dump> <pass>
2 /dev/sda1                       none            swap    sw       0      0

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 red one!)

1 ls /sys/class/leds/


Debian’s init must be run with PID 1. The boot process of OpenWRT is simple

  1. (device-specific stuff happens)
  2. /etc/preinit is launched with PID 1
  3. /etc/preinit execs /sbin/init
  4. /sbin/init execs /sbin/procdOpenWRT’s new all-singing all-dancing everything-replacement init system
  5. (stuff happens)
  6. /etc/preinit launched as a child of procd
  7. (stuff happens)

The idea is to rewire the boot process to

  1. (device-specific stuff happens)
  2. /etc/preinit is launched with PID 1
  3. /etc/preinit execs Debian’s init OR continues boot

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)

1 [ -z "$PREINIT" ] && exec /sbin/init

This line should be the first line. Above this line we insert

1 [ $$ -eq 1 ] && . /etc/debian_boot >>/debian.log 2>&1

This means it only runs the first time (when PID is 1) and logs stderr and stdout to /debian.log on the NAND

 1 #!/bin/sh
 2 USB="/dev/sda2"
 3 WAIT=5
 5 echo "===================="
 6 date
 7 mount -t proc proc /proc
 8 mount -t sysfs sys /sys
 9 echo "Kernel filesystems mounted."
11 for module in ehci-hcd ehci-platform ltq_hcd_danube scsi_mod sd_mod usb-storage jbd2 ext4; do
12     echo "Loading $module"
13     modprobe $module
14 done
15 echo "Modules loaded."
17 mkdir -p /debian
18 for i in $(seq 0 $WAIT); do
19     echo "Waiting $i seconds."
20     mount -o rw,sync,noatime "$USB" /debian && break
21     sleep 1
22 done
24 if [ -e /debian/sbin/init -o -L /debian/sbin/init ]; then
25     echo "Linux installation found."
26     echo 255 > "/sys/class/leds/soc:orange:upgrading/brightness"
27     cd /debian
28     mkdir -p openwrt
29     pivot_root . openwrt
30     echo "Starting /sbin/init."
31     exec /sbin/init
32 fi
34 umount /debian
35 umount /sys
36 umount /proc
37 echo "Falling back to OpenWRT."

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.

1 reboot

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 :wink:

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 journal.

Finally, check if you got the configuration options correct for OpenWRT and the kernel. Easy mistake to make!


Hello World

ruby -e 'puts "Hello World"'

This is a blog

Yep. It’s a blog. It’s my blog. Why? Because it’s useful.

It’s useful to me and hopefully, it’ll be useful to others. It’ll be a place for me to document things for me to look back on and for unsuspecting interneters to find.

It’ll be an adventure of moaning and coding and you’ll be my sounding board as I try different stuff out. And guess what? It’s open source!

TL;DR: It’s a blog about programming and stuff. Also, this is the first post. But it is the second post.

EDIT: Due to the new sorting mechanism, this is now the first post in the archives :confused:


Jekyll: blogging for fun and profit

From nothing to blog in under a day

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… :laughing:

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.

Maybe it isn’t as advanced as Jekyll New or as robust as Bootstrap but it’s configurable, nice-looking, and it works on smaller displays using @media rules — the right way to do things. Also, it works on IE 5.5. :no_mouth:

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. :blush:

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 == awesome.

NOTE: I had absolutely no Ruby experience before starting this blog :wink:

NOTE: After finishing this post, I immediately proceeded to rewrite all the SCSS as it was not clean enough for me :expressionless: