public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Initramfs from existing vmlinuz
@ 2008-12-23 22:28 Martin Schlemmer
  2008-12-23 23:34 ` Willy Tarreau
  0 siblings, 1 reply; 7+ messages in thread
From: Martin Schlemmer @ 2008-12-23 22:28 UTC (permalink / raw)
  To: linux-kernel

Hi

I had a bit of an accident, and wondered if somebody already had to try to extract the initramfs image from an existing vmlinuz?

 I did try google, but either my search terms was not right, or nobody really touched on the subject before, because all the results mostly dealt with an external image.

Any advice will be appreciated.


Thanks

MS



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Initramfs from existing vmlinuz
  2008-12-23 22:28 Initramfs from existing vmlinuz Martin Schlemmer
@ 2008-12-23 23:34 ` Willy Tarreau
  2008-12-24 11:37   ` Martin Schlemmer
  2009-01-05 11:12   ` Initramfs from existing vmlinuz Ian Campbell
  0 siblings, 2 replies; 7+ messages in thread
From: Willy Tarreau @ 2008-12-23 23:34 UTC (permalink / raw)
  To: Martin Schlemmer; +Cc: linux-kernel

On Wed, Dec 24, 2008 at 12:28:53AM +0200, Martin Schlemmer wrote:
> Hi
> 
> I had a bit of an accident, and wondered if somebody already had to try to extract the initramfs image from an existing vmlinuz?
> 
>  I did try google, but either my search terms was not right, or nobody really touched on the subject before, because all the results mostly dealt with an external image.
> 
> Any advice will be appreciated.

yes, it happens to me from time to time.
You first have to extract and uncompress the ELF image from vmlinuz. For
this, look for the gzip signature 1F 8B 08 in your vmlinuz, and feed all
data starting from this point to zcat. Either you do the same on the
resulting file -and you may find several compressed images- or you simply
pass it through "objdump -h". It will show you a .init.ramfs section. Use
the fourth field as the file offset, and dump from that position. You'll
find your initramfs, likely starting with 1F 8B 08 since it's supposed
to be compressed with gzip.

You need an hex editor, dd, zcat and objdump for this. It's not much
complicated once you have the tools, but it might require a few attempts
before finding the right image (I tend to find config.gz before initramfs).

Regards,
Willy


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Initramfs from existing vmlinuz
  2008-12-23 23:34 ` Willy Tarreau
@ 2008-12-24 11:37   ` Martin Schlemmer
  2008-12-25 17:55     ` Martin Schlemmer
  2008-12-25 18:17     ` Initramfs from existing vmlinuz (#2) Martin Schlemmer
  2009-01-05 11:12   ` Initramfs from existing vmlinuz Ian Campbell
  1 sibling, 2 replies; 7+ messages in thread
From: Martin Schlemmer @ 2008-12-24 11:37 UTC (permalink / raw)
  To: Willy Tarreau, Martin Schlemmer; +Cc: linux-kernel

>>> On 2008/12/24 at 01:34 AM, Willy Tarreau <w@1wt.eu> wrote:
> On Wed, Dec 24, 2008 at 12:28:53AM +0200, Martin Schlemmer wrote:

Hi Willy

>> I had a bit of an accident, and wondered if somebody already had to try to 
> extract the initramfs image from an existing vmlinuz?
>> 
>>  I did try google, but either my search terms was not right, or nobody 
> really touched on the subject before, because all the results mostly dealt 
> with an external image.
>> 
>> Any advice will be appreciated.
> 
> yes, it happens to me from time to time.
> You first have to extract and uncompress the ELF image from vmlinuz. For
> this, look for the gzip signature 1F 8B 08 in your vmlinuz, and feed all
> data starting from this point to zcat. Either you do the same on the
> resulting file -and you may find several compressed images- or you simply
> pass it through "objdump -h". It will show you a .init.ramfs section. Use
> the fourth field as the file offset, and dump from that position. You'll
> find your initramfs, likely starting with 1F 8B 08 since it's supposed
> to be compressed with gzip.
> 
> You need an hex editor, dd, zcat and objdump for this. It's not much
> complicated once you have the tools, but it might require a few attempts
> before finding the right image (I tend to find config.gz before initramfs).
> 

Appreciated, I should be able to go from here now - just getting the starting point is sometimes the main issue.


Thanks

M



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Initramfs from existing vmlinuz
  2008-12-24 11:37   ` Martin Schlemmer
@ 2008-12-25 17:55     ` Martin Schlemmer
  2008-12-25 18:17     ` Initramfs from existing vmlinuz (#2) Martin Schlemmer
  1 sibling, 0 replies; 7+ messages in thread
From: Martin Schlemmer @ 2008-12-25 17:55 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1688 bytes --]

>>> On 2008/12/24 at 01:37 PM, "Martin Schlemmer" <Martin.Schlemmer@nwu.ac.za>
wrote:
>>>> On 2008/12/24 at 01:34 AM, Willy Tarreau <w@1wt.eu> wrote:
>> On Wed, Dec 24, 2008 at 12:28:53AM +0200, Martin Schlemmer wrote:
 
Hi
 
>>> I had a bit of an accident, and wondered if somebody already had to try to 
>> extract the initramfs image from an existing vmlinuz?
>>> 
>>>  I did try google, but either my search terms was not right, or nobody 
>> really touched on the subject before, because all the results mostly dealt 
>> with an external image.
>>> 
>>> Any advice will be appreciated.
>> 
>> yes, it happens to me from time to time.
>> You first have to extract and uncompress the ELF image from vmlinuz. For
>> this, look for the gzip signature 1F 8B 08 in your vmlinuz, and feed all
>> data starting from this point to zcat. Either you do the same on the
>> resulting file -and you may find several compressed images- or you simply
>> pass it through "objdump -h". It will show you a .init.ramfs section. Use
>> the fourth field as the file offset, and dump from that position. You'll
>> find your initramfs, likely starting with 1F 8B 08 since it's supposed
>> to be compressed with gzip.
>> 
>> You need an hex editor, dd, zcat and objdump for this. It's not much
>> complicated once you have the tools, but it might require a few attempts
>> before finding the right image (I tend to find config.gz before initramfs).
>> 
> 
> Appreciated, I should be able to go from here now - just getting the starting 
> point is sometimes the main issue.
> 

Simple Perl script to do above in case anybody might find it useful in the future.


M



[-- Attachment #2: extract_initramfs.pl --]
[-- Type: application/octet-stream, Size: 2103 bytes --]

#!/usr/bin/perl
#
# extract_initramfs.pl: extracts the initramfs out of a packed kernel image
#
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
#
# Released under the terms of the GNU GPL
#

use strict;
use warnings;

use Cwd;
use Encode;
use IO::File;
use IO::Pipe;
use IO::Uncompress::Gunzip qw (gunzip $GunzipError);

if (! defined ($ARGV[0]) && ! defined ($ARGV[1])) {
	print "usage: $0 VMLINUZ [VMLINUX] [INITRAMFS_IMAGE]\n";
	exit (1);
}

if (! -f $ARGV[0]) {
	print "$ARGV[0] does not exists\n";
	exit (1);
}

my ($input,$vm_output,$rm_output) = @ARGV;

$vm_output = cwd . '/vmlinux',
	if (! defined ($vm_output) || $vm_output eq '');
$rm_output = cwd . '/initramfs.cpio.gz',
	if (! defined ($rm_output) || $rm_output eq '');

eval {
	my $fh = IO::File->new;

	$fh->open ($ARGV[0]) or die ($!);
	$fh->binmode;

	my $data;
	my $count = 0;

	do {
		$data = '';

		$fh->seek ($count++, 0) or die ($!);
		$fh->read ($data, 3) or die ($!);

	} until ($data =~ /^\x{1F}\x{8B}\x{08}$/ || $fh->eof);

	if ($data !~ /^\x{1F}\x{8B}\x{08}$/ || $fh->eof) {
		print STDERR "Could not find GZIP marker!\n";
		exit (1);
	}

	$fh->seek (--$count, 0) or die ($!);

	$data = '';

	while (! $fh->eof) {
		my $buffer;

		$fh->read ($buffer, 2048) or die ($!);
		$data .= $buffer;
	}
	$fh->close;

	my $image;

	gunzip \$data => \$image,
        or die ("Gunzip failed: $GunzipError\n");

	$fh->open ($vm_output, '>') or die ($!);
	$fh->binmode;
	$fh->write ($image) or die ($!);
	$fh->close;

	my $have_ramfs = 0;
	my $pipe = IO::Pipe->new or die ($!);

	$pipe->reader ('objdump', '-h', $vm_output) or die ($!);

	while (my $line = $pipe->getline) {
		if ($line =~ /^\s+\d+\s+(\S+)\s+(\S+)\s+\S+\s+\S+\s+(\S+)\s+/) {
			my ($section,$size,$offset) = ($1,$2,$3);

			next if ($section ne '.init.ramfs');

			$fh->open ($rm_output, '>') or die ($!);
			$fh->write ($image, hex ($size), hex ($offset)) or die ($!);
			$fh->close;

			$have_ramfs = 1;

			last;
		}
	}

	$pipe->close;

	die ('No \'.init.ramfs\' section found!') if (! $have_ramfs);
};
if ($@) {
	printf STDERR "$@\n";
	exit (1);
}

exit (0);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Initramfs from existing vmlinuz (#2)
  2008-12-24 11:37   ` Martin Schlemmer
  2008-12-25 17:55     ` Martin Schlemmer
@ 2008-12-25 18:17     ` Martin Schlemmer
  1 sibling, 0 replies; 7+ messages in thread
From: Martin Schlemmer @ 2008-12-25 18:17 UTC (permalink / raw)
  To: Willy Tarreau, Martin Schlemmer; +Cc: linux-kernel

>>> On 2008/12/24 at 01:37 PM, "Martin Schlemmer" <Martin.Schlemmer@nwu.ac.za>
wrote:
>>>> On 2008/12/24 at 01:34 AM, Willy Tarreau <w@1wt.eu> wrote:
>> On Wed, Dec 24, 2008 at 12:28:53AM +0200, Martin Schlemmer wrote:
 
Hi
 
>>> I had a bit of an accident, and wondered if somebody already had to try to 
>> extract the initramfs image from an existing vmlinuz?
>>> 
>>>  I did try google, but either my search terms was not right, or nobody 
>> really touched on the subject before, because all the results mostly dealt 
>> with an external image.
>>> 
>>> Any advice will be appreciated.
>> 
>> yes, it happens to me from time to time.
>> You first have to extract and uncompress the ELF image from vmlinuz. For
>> this, look for the gzip signature 1F 8B 08 in your vmlinuz, and feed all
>> data starting from this point to zcat. Either you do the same on the
>> resulting file -and you may find several compressed images- or you simply
>> pass it through "objdump -h". It will show you a .init.ramfs section. Use
>> the fourth field as the file offset, and dump from that position. You'll
>> find your initramfs, likely starting with 1F 8B 08 since it's supposed
>> to be compressed with gzip.
>> 
>> You need an hex editor, dd, zcat and objdump for this. It's not much
>> complicated once you have the tools, but it might require a few attempts
>> before finding the right image (I tend to find config.gz before initramfs).
>> 
> 

Not sure if the previous post got through due to mail scanner, but it was also an older version.

Anyhow, below is a simple Perl script to do above if anybody ever have the same need in the future.


M

-------------------------------
#!/usr/bin/perl
#
# extract_initramfs.pl: extracts the initramfs out of a packed kernel image
#
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
#
# Released under the terms of the GNU GPL
#

use strict;
use warnings;

use Cwd;
use Encode;
use IO::File;
use IO::Pipe;
use IO::Uncompress::Gunzip qw (gunzip $GunzipError);

my ($input,$vm_output,$rfs_output) = @ARGV;

$vm_output = cwd . '/vmlinux',
	if (! defined ($vm_output) || $vm_output eq '');
$rfs_output = cwd . '/initramfs.cpio.gz',
	if (! defined ($rfs_output) || $rfs_output eq '');

if (! defined ($input)) {
	print "usage: $0 VMLINUZ [VMLINUX] [INITRAMFS_IMAGE]\n";
	exit (1);
}

if (! -f $input) {
	print "'$input' does not exist!\n";
	exit (1);
}

eval {
	my $fh = IO::File->new;

	$fh->open ($input) or die ($!);
	$fh->binmode;

	my $data;
	my $count = 0;

	do {
		$data = '';

		$fh->seek ($count++, 0) or die ($!);
		$fh->read ($data, 3) or die ($!);

	} until ($data eq "\x1F\x8B\x08" || $fh->eof);

	if ($data ne "\x1F\x8B\x08" || $fh->eof) {
		print STDERR "Could not find GZIP marker!\n";
		exit (1);
	}

	$fh->seek (--$count, 0) or die ($!);

	$data = '';

	while (! $fh->eof) {
		my $buffer;

		$fh->read ($buffer, 2048) or die ($!);
		$data .= $buffer;
	}
	$fh->close;

	my $image_data;

	gunzip \$data => \$image_data,
        or die ("Gunzip failed: $GunzipError\n");

	$fh->open ($vm_output, '>') or die ($!);
	$fh->binmode;
	$fh->write ($image_data) or die ($!);
	$fh->close;

	my $have_ramfs = 0;
	my $pipe = IO::Pipe->new or die ($!);

	$pipe->reader ('objdump', '-h', $vm_output) or die ($!);

	while (my $line = $pipe->getline) {
		if ($line =~ /^\s+\d+\s+(\S+)\s+(\S+)\s+\S+\s+\S+\s+(\S+)\s+/) {
			my ($section,$size,$offset) = ($1,$2,$3);

			next if ($section ne '.init.ramfs');

			$fh->open ($rfs_output, '>') or die ($!);
			$fh->write ($image_data, hex ($size), hex ($offset)) or die ($!);
			$fh->close;

			$have_ramfs = 1;

			last;
		}
	}

	$pipe->close;

	die ('No \'.init.ramfs\' section found!') if (! $have_ramfs);
};
if ($@) {
	printf STDERR "$@\n";
	exit (1);
}

exit (0);



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Initramfs from existing vmlinuz
  2008-12-23 23:34 ` Willy Tarreau
  2008-12-24 11:37   ` Martin Schlemmer
@ 2009-01-05 11:12   ` Ian Campbell
  2009-01-05 11:47     ` Willy Tarreau
  1 sibling, 1 reply; 7+ messages in thread
From: Ian Campbell @ 2009-01-05 11:12 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Martin Schlemmer, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 730 bytes --]

On Wed, 2008-12-24 at 00:34 +0100, Willy Tarreau wrote:
> You first have to extract and uncompress the ELF image from vmlinuz.
> For this, look for the gzip signature 1F 8B 08 in your vmlinuz, and
> feed all data starting from this point to zcat.

Since v2.6.26 (I think, it was v2.08 of the x86 bzImage format anyhow,
which was the same point the payload became ELF formatted) you can find
it directly using the payload_offset and payload_length fields in the
bzImage header. Attached bzexplode.c demonstrates this. e.g. "bzexplode
vmlinuz | zcat > vmlinux.elf"

Ian.

-- 
Ian Campbell
Current Noise: Electric Wizard - Saturn's Children

A likely impossibility is always preferable to an unconvincing possibility.
		-- Aristotle

[-- Attachment #2: bzexplode.c --]
[-- Type: text/x-csrc, Size: 1251 bytes --]

#include <stdio.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>

#include <inttypes.h>

#include <err.h>

#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>

int main(int argc, char **argv)
{
	int fd;
	struct stat sb;
	void *p;
	uint8_t *hdr;
	int setup_sectors;
	uint32_t compressed_payload_offset;
	uint32_t compressed_payload_length;

	if (argc != 2)
		errx(1, "usage: bzexplode <bzImage>");

	fd = open(argv[1], O_RDONLY);
	if (fd < 0)
		err(1, "open");

	if (fstat(fd, &sb) < 0)
		err(1, "fstat");

	p = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
	if (p == MAP_FAILED)
		err(1, "mmap");

	hdr = p;
	setup_sectors = hdr[0x1f1];
	compressed_payload_offset = *(uint32_t*)&hdr[0x248];

	fprintf(stderr, "setup sectors %d\n", setup_sectors);

	compressed_payload_offset += (setup_sectors+1) * 512;

	//compressed_payload_length = *(uint32_t*)(p + compressed_payload_offset - 4);
	compressed_payload_length = *(uint32_t*)&hdr[0x24c];

	fprintf(stderr, "compressed_payload_offset %"PRIx32" (abs)\n",
		compressed_payload_offset);
	fprintf(stderr, "compressed_payload_length %"PRIx32"\n",
		compressed_payload_length);

	write(1,
	      p + compressed_payload_offset,
	      compressed_payload_length);
	return 0;
}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Initramfs from existing vmlinuz
  2009-01-05 11:12   ` Initramfs from existing vmlinuz Ian Campbell
@ 2009-01-05 11:47     ` Willy Tarreau
  0 siblings, 0 replies; 7+ messages in thread
From: Willy Tarreau @ 2009-01-05 11:47 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Martin Schlemmer, linux-kernel

On Mon, Jan 05, 2009 at 11:12:26AM +0000, Ian Campbell wrote:
> On Wed, 2008-12-24 at 00:34 +0100, Willy Tarreau wrote:
> > You first have to extract and uncompress the ELF image from vmlinuz.
> > For this, look for the gzip signature 1F 8B 08 in your vmlinuz, and
> > feed all data starting from this point to zcat.
> 
> Since v2.6.26 (I think, it was v2.08 of the x86 bzImage format anyhow,
> which was the same point the payload became ELF formatted) you can find
> it directly using the payload_offset and payload_length fields in the
> bzImage header. Attached bzexplode.c demonstrates this. e.g. "bzexplode
> vmlinuz | zcat > vmlinux.elf"

Thanks Ian.

Indeed, I'm sure this will be useful from time to time!

Cheers,
Willy


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-01-05 11:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-23 22:28 Initramfs from existing vmlinuz Martin Schlemmer
2008-12-23 23:34 ` Willy Tarreau
2008-12-24 11:37   ` Martin Schlemmer
2008-12-25 17:55     ` Martin Schlemmer
2008-12-25 18:17     ` Initramfs from existing vmlinuz (#2) Martin Schlemmer
2009-01-05 11:12   ` Initramfs from existing vmlinuz Ian Campbell
2009-01-05 11:47     ` Willy Tarreau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox