6

I am working on a shell script. I have a pre-built zImage. is it possible to know the kernel version from which this zImage was created?

I have tried with the commands updated @ Getting uname information from a compressed kernel image, but both commands are failing.

$ dd if=zImage bs=1 skip=$(LC_ALL=C grep -a -b -o $'\x1f\x8b\x08\x00\x00\x00\x00\x00' zImage | \
  cut -d ':' -f 1) | zcat | grep -a 'Linux version'

dd: unrecognized operand `3165585'
Try `dd --help' for more information.

gzip: stdin: unexpected end of file

$ dd if=zImage bs=1 skip=$(LC_ALL=C grep -a -b -o $'\xFD\x37\x7A\x58\x5A\x00' zImage | \
  head -n 1 | cut -d ':' -f 1) | xzcat | grep -a 'Linux version'

xzcat: (stdin): File format not recognized

Can you guide me to identify the kernel version from zImage.

Community
  • 1
  • 1
Ravi A
  • 421
  • 2
  • 9
  • 21
  • 1
    For ARM targets, the [Makefile](http://lxr.free-electrons.com/source/arch/arm/boot/compressed/Makefile) indicates that a zImage can be compressed using gzip, lzo, lzma, xz, or lz4 methods. You have tried only two (gzip and xz) of the five possible methods. – sawdust Jun 07 '16 at 19:12

2 Answers2

13

Check kernel compression algorithm

Most likely your zImage was compressed using LZMA compressor. You can check it in next files:

  • in .config file (if you built kernel by yourself)
  • in /boot/config-`uname -r` file (if you are using your distribution)
  • in /proc/config.gz file (if CONFIG_IKCONFIG_PROC is enabled)

Look for CONFIG_KERNEL_* param:

$ cat .config | grep '^CONFIG_KERNEL_[^_]\+='

If you have CONFIG_KERNEL_LZMA=y set, it means LZMA compressor is used.

Unpack zImage

LZMA format has 5d 00 00 header signature. So one can find position of compressed Image file in zImage file this way:

$ grep -P -a -b -m 1 --only-matching '\x5D\x00\x00' zImage | cut -f 1 -d :

To extract compressed Image:

$ pos=$(grep -P -a -b -m 1 --only-matching '\x5D\x00\x00' zImage | cut -f 1 -d :)
$ dd if=arch/arm/boot/zImage of=piggy.lzma bs=1 skip=$pos

Now make sure that piggy.lzma is actually LZMA archive:

$ file piggy.lzma 

piggy.lzma: LZMA compressed data, streamed

Decompress piggy.lzma:

$ unlzma -c piggy.lzma > Image

Find the Linux version

Now that you have unpacked Image, you can find the Linux version using strings tool:

$ strings Image | grep 'Linux version'

which should give you something like this:

Linux version 4.4.11-188843-g94c4bf5-dirty (joe@joe-laptop) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu May 26 20:55:27 EEST 2016

Sam Protsenko
  • 14,045
  • 4
  • 59
  • 75
  • thanks for the details it worked. Is it possible to know which compression technique used for compression from the zImage. – Ravi A Jul 08 '16 at 08:01
  • 3
    1. Try to use "binwalk" tool (should be in your distro repository). 2. Also you can try to check your image with "file" tool. 3. You can try to extract "piggy" file using all known kernel compression algorithms (and corresponding magic number in header), then check "piggy" file with "file" tool, it should tell you if it's expected compressed file. Other than that I don't know any easy way to figure out the compression algorithm. – Sam Protsenko Jul 08 '16 at 11:01
  • 1
    Using `dd if=zImage of=piggy.lzma skip=$pos iflag=skip_bytes` instead of `dd if=zImage of=piggy.lzma bs=1 skip=$pos` was amazingly faster for me. – Alexandre Schmidt Mar 07 '19 at 20:51
  • For xz compressed what to search instead of `5d 00 00` ? – Darren Ng Aug 14 '21 at 15:58
  • 1
    @DarrenNg Try to look for `fd377a585a00`, as stated [here](http://www.who.is.free.fr/wiki/doku.php?id=cli). I didn't check that though. – Sam Protsenko Aug 15 '21 at 22:38
0

An addition to Sam Protsenko's answer:

Since you do not clarify the compression algorithm used in the zImage file, I recommend you to use vmlinux-to-elf. This tool can be used to convert a zImage file to ELF file, and can recognize multiple compression algorithms(not only LZMA).

In a simple usecase, first convert a zImage file to ELF file:

./vmlinux-to-elf ./zImage ./Image
file ./Image

./Image: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, not stripped

Then, find the linux version with strings

strings ./Image | grep 'Linux version'

Linux version 3.4.0-gd59db4e (android-build@vpbs1.mtv.corp.google.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Mon Mar 17 15:16:36 PDT 2014

imlk
  • 73
  • 1
  • 4
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/30546808) – jiwopene Dec 14 '21 at 17:23
  • 1
    @jiwopene Thanks you for your reminder, I have made some changes to the answer. :) – imlk Dec 16 '21 at 04:17