Unzipping a Kernel Image

Bruce Elliott (belliott@accessone.com)
Sun, 20 Jul 1997 23:54:26 -0700 (PDT)


> I keep getting this with 2.1.45:
> lock from interrupt context at [do_page_fault+0x2b]
> ugh at [do_page_fault+0x48]
> Nothing else - system is dead after that (can't even telnet in).
>
> P.S. How do you unzip a compressed kernel image? Sure would help
> at times to be able to objdump it.
>
> --
> Andrew E. Mileski mailto:aem@netcom.ca

Here is a very simple program that tears the image apart. It simply scans
looking for the gzip magic numbers and copies the rest. The output can
then be un-gzip-ped, with a harmless complaint about some extra stuff on
the end.

As an example, a pseudo-uname can be done as:

breakzi /boot/zImage.2.1.42 | gzip -d | strings -a | grep '^Linux version'

=================================================================
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>

/*
# Gzip
0 string \037\213 gzip compressed data
>2 byte 8 - deflate method
>3 byte &0x1 , ascii
>3 byte &0x2 , continuation
>3 byte &0x4 , extra field
>3 byte &0x8 , original file name
>3 byte &0x10 , comment
>3 byte &0x20 , encrypted
>8 byte 2 , max compression
>8 byte 4 , max speed
*/

#define BSIZE 4096
#define C1 037
#define C2 0213
#define C3 8

main(int argc, char **argv)
{
unsigned char *bbuf;
int bc;
int ifd = 0;
int ofd = 1;

if (argc > 3) {
fprintf(stderr, "usage: breakzi [in-file [out-file]]\n");
exit(1);
}
if (argc > 1) {
if ((ifd = open(argv[1], O_RDONLY)) < 0) {
perror(argv[1]);
exit(1);
}
}
if (argc > 2) {
if ((ofd = open(argv[2], O_WRONLY | O_CREAT, 0755)) < 0) {
perror(argv[2]);
exit(1);
}
}
if ((bbuf = (char *)malloc(BSIZE)) < 0) {
perror("bbuf");
exit(1);
}
while (1) {
readbyt(ifd, bbuf + 0);
if (bbuf[0] != C1) {
continue;
}
overlap:
readbyt(ifd, bbuf + 1);
if (bbuf[1] != C2) {
if (bbuf[1] == C1) {
bbuf[0] = C1;
goto overlap;
}
continue;
}
readbyt(ifd, bbuf + 2);
if (bbuf[2] != C3) {
if (bbuf[2] == C1) {
bbuf[0] = C1;
goto overlap;
}
continue;
}
break;
}
write(ofd, bbuf, 3);
while (bc = read(ifd, bbuf, BSIZE)) {
write(ofd, bbuf, bc);
}
}

readbyt(int ifd, char *buf)
{
int bc;

if ((bc = read(ifd, buf, 1)) != 1) {
fprintf(stderr, "EOF encountered before header\n");
exit(1);
}
}
=================================================================

B. D. Elliott bde@accessone.com (Seattle)