Steps to make a change to a binary (already compiled) kernel

Steps to make a change to a binary (already compiled) kernel

Take a bzImage
Unpack it with mkvmlinux
This will provide you with 3 parts:
bootsector, setup, and system
(Currently the unpacker gives you no permissions, so do chmod a+rw bootsector setup system)

system is composed of (at least) 2 parts
header and data

The data section is the kernel proper in gzip format. You will notice the data (gzipped kernel) begins with the gzip signiture of “1f 8b 08”. Just prior to this is just a handfull of values and a lot of “00” padding. The data section in my “system” starts around offset 3650 (IIRC – If I Recall Correctly).

Note what the offset is, then convert that hex value to decimal

bc
ibase=16
3650

Then dd out the header and data
dd if=system of=header bs=1 count=13904
dd if=system of=kernel.gz bs=1 skip=13904

Now unzip the kernel:
gunzip kernel.gz

Now convert to hex and then make any modifications you need to the kernel.

xxd -g 1 kernel kernel.hex

My need is to change the Serial I/O port from 0x3f8 to 0x400, so I find my appropriate section which has “c2 01 00 f8 03” (note that most everything has reverse order), then I make my change to “c2 01 00 00 04”. Now it’s time to repack.

Convert from hex back to binary:

xxd -r kernel.hex kernel.new

Compress the kernel

cat kernel.new | gzip -n9 > kernel.new.gz

The tail end of the header contains the length of the ?gzipped? kernel. So do a ls -l kernel.new.gz and convert that to hex:

bc
obase=16
110506

So that means that you have to convert the header to hex, update the size, then repack it:

xxd -g 1 header header.hex

xxd -r header.hex header.new

Put back the header and kernel:
cat header.new kernel.new.gz > system.new

Now put back the 3 main pieces:

./mkvmlinuz -b -o bzImage.new bootsect setup system.new

Now boot on the new bzImage

Notes:
Make sure that bytes 501 and 500 of are still able to contain the size (in blocks of 16, rounded up) of the system.new.

The above doesn’t have accurate numbers with each of the examples yet.

In the above example my gzipped kernel was 2 bytes larger than the previous. Without updating the header size info I got “ran out of input data”. Now after updating the header size info, I get something like “length error”. So I am still missing a value somewhere.

Leave a Comment