How to recover and decompress a Linux kernel dumped MTD partition

I used the “dd” utility to recover the kernel image from my IP Camera. Now I want to analyze it.

$ cp mtd2_Kernel.img /tmp/

Let see how is the kernel image:

$ file mtd2_Kernel.img
mtd2_Kernel.img: u-boot legacy uImage, Linux-2.6.24ssl, Linux/ARM, OS Kernel Image (Not compressed), 1467600 bytes, Mon Apr  8 16:01:50 2013, Load Address: 0x50C08000, Entry Point: 0x50C08000, Header CRC: 0xFFA94C01, Data CRC: 0xA90B8571

Hmm, it is u-boot uImage, let us to remove the u-boot header:

$ dd if=mtd2_Kernel.img of=Image bs=64 skip=1
23551+0 records in
23551+0 records out
1507264 bytes (1.5 MB) copied, 0.0529103 s, 28.5 MB/s

Let see now:

$ file Image 
Image: Linux kernel ARM boot executable zImage (little-endian)

Hmm, it is a zImage file, if I rename it and try to extract?

$ mv Image Image.gz
$ gunzip Image.gz
gzip: Image.gz: not in gzip format

No way!

(After more search I found this suggestions)

Let try it:

$ mv Image.gz zImage
$ arm-linux-objdump -EL -b binary -D -m armv5t zImage | grep 8b1f
    31e4:	00088b1f 	andeq	r8, r8, pc, lsl fp
   28404:	6c8b1f44 	stcvs	15, cr1, [fp], {68}
   36464:	e8b1f4f9 	ldmia	r1!, {r0, r3, r4, r5, r6, r7, sl, ip, sp, lr, pc}

We are interested only in the first address (31e4 = 12772)

$ dd if=zImage of=piggy.gz bs=1 skip=12772
1494492+0 records in
1494492+0 records out
1494492 bytes (1.5 MB) copied, 2.36995 s, 631 kB/s

And finally:

$ file piggy.gz 
piggy.gz: gzip compressed data, last modified: Mon Apr  8 16:01:49 2013, max compression, from Unix

$ gunzip piggy.gz

gzip: piggy.gz: decompression OK, trailing garbage ignored


Now I can inspect the kernel symbols because /proc/ksyms and /proc/kallsyms are not present.