J'utilise Debian Live-Build-Build pour travailler sur un système amorçable. À la fin du processus, je reçois les fichiers typiques utilisés pour démarrer un système en direct: un fichier SquashFs, certains GRUB modules et fichiers de configuration et un fichier initrd.img.
Je peux démarrer très bien en utilisant ces fichiers, en passant l'intite au noyau via
initrd=/path/to/my/initrd.img
sur la ligne de commande de bootloader. Mais quand j'essaie d'examiner le contenu de mon image InitiDrd, comme si:
$file initrd.img
initrd.img: ASCII cpio archive (SVR4 with no CRC)
$mkdir initTree && cd initTree
$cpio -idv < ../initrd.img
l'arbre de fichier que je reçois ressemble à ceci:
$tree --charset=ASCII
.
`-- kernel
`-- x86
`-- microcode
`-- GenuineIntel.bin
Où est l'arborescence du système de fichiers, avec le typique/corbeille,/etc,/sbin ... contenant les fichiers réels utilisés pendant la démarrage?
La méthode de saut de bloc CPIO donné ne fonctionne pas de manière fiable. C'est parce que les images d'initiation que je me plaisaient n'avaient pas les deux archives concaténées sur une limite de 512 octets.
Fais cela:
apt-get install binwalk
legolas [mc]# binwalk initrd.img
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 ASCII cpio archive (SVR4 with no CRC), file name: "kernel", file name length: "0x00000007", file size: "0x00000000"
120 0x78 ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86", file name length: "0x0000000B", file size: "0x00000000"
244 0xF4 ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode", file name length: "0x00000015", file size: "0x00000000"
376 0x178 ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode/GenuineIntel.bin", file name length: "0x00000026", file size: "0x00005000"
21004 0x520C ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"
21136 0x5290 gzip compressed data, from Unix, last modified: Sat Feb 28 09:46:24 2015
Utilisez le dernier numéro (21136) qui ne figure pas sur une limite de 512 octets pour moi:
legolas [mc]# dd if=initrd.img bs=21136 skip=1 | gunzip | cpio -tdv | head
drwxr-xr-x 1 root root 0 Feb 28 09:46 .
drwxr-xr-x 1 root root 0 Feb 28 09:46 bin
-rwxr-xr-x 1 root root 554424 Dec 17 2011 bin/busybox
lrwxrwxrwx 1 root root 7 Feb 28 09:46 bin/sh -> busybox
-rwxr-xr-x 1 root root 111288 Sep 23 2011 bin/loadkeys
-rwxr-xr-x 1 root root 2800 Aug 19 2013 bin/cat
-rwxr-xr-x 1 root root 856 Aug 19 2013 bin/chroot
-rwxr-xr-x 1 root root 5224 Aug 19 2013 bin/cpio
-rwxr-xr-x 1 root root 3936 Aug 19 2013 bin/dd
-rwxr-xr-x 1 root root 984 Aug 19 2013 bin/dmesg
Si vous connaissez votre initrd.img
consiste en une archive CPIO non compressée, suivie d'une archive CPIO compressée GZ, vous pouvez utiliser ce qui suit pour extraire tous les fichiers (à partir des deux archives) dans votre répertoire de travail actuel (testé dans Bash):
(cpio -id; zcat | cpio -id) < /path/to/initrd.img
La ligne de commande ci-dessus transmet le contenu de initrd.img
En tant qu'entrée standard dans un sous-groupe qui exécute les deux commandes cpio -id
et zcat | cpio -id
séquentiellement. La première commande (cpio -id
) se termine une fois que cela a lu toutes les données appartenant à la première archive CPIO. Le contenu restant est ensuite transmis à zcat | cpio -id
, qui décompresse et déballe la deuxième archive.
Il s'avère généré par la construction en direct de Debian (et à ma surprise acceptée par le noyau) est en réalité la concaténation de deux images:
Lors de l'extraction de l'initial InitiDRD.IMG, hors sortie de la sortie en direct, j'ai reçu cette sortie:
$cpio -idv ../initrd.img
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/GenuineIntel.bin
896 blocks
Ce qui signifie que l'extraction CPIO s'est terminée après avoir analysé 896 blocs de 512 octets chacun. Mais l'initial Initird.img était beaucoup plus grand que 896 * 512 = 458752B = 448 Ko:
$ls -liah initrd.img
3933924 -r--r--r-- 1 root root 21M Oct 21 10:05 initrd.img
Donc, l'image initiative réelle que je cherchais a été ajoutée juste après la première archive CPIO (celle contenant les mises à jour du microcode) et peut être consulté à l'aide de DD:
$dd if=initrd.img of=myActualInitrdImage.img.gz bs=512 skip=896
Basé sur l'idée donnée dans la réponse de @ Woolpool, j'ai écrit une fonction récursive qui fonctionnera pour toutes les archives CPIO, quel que soit l'arrangement des données concaténées et ne nécessite aucun outil spécial tel que Binwalk. Par exemple, mes mkinitramfs produisaient un CPIO; CPIO; fichier gzip. Cela fonctionne en extrayant chaque partie du fichier initial concaténé, enregistrant le reste dans un temp ... à l'aide du programme "Fichier" pour décider quoi faire avec la partie suivante.
uncpio(){
if [[ $(wc -c $1 | cut -d ' ' -f1) -eq 0 ]]; then
return
fi
type=$(cat $1 | file -)
local tmpfile=$(date +%s.%N)
echo -e "\n$type"
if [[ $type =~ .*cpio.* ]]; then
cat $1 | (cpio -id; cat >$tmpfile)
Elif [[ $type =~ .*gzip.* ]]; then
zcat $1 | (cpio -id; cat >$tmpfile)
else
return
fi
uncpio $tmpfile
rm $tmpfile
}
Pour utiliser Type: UNCPIO InitiDRDFileName
Vous pouvez utiliser unmkinitramfs
des outils Inititramfs> = 0,126, qui est inclus depuis Debian 9 (Stretch) et Ubuntu 18.04 (Bionic).
Si vous avez besoin d'exécuter cette tâche souvent, vous pouvez créer une petite fonction Bash comme ci-dessous (et peut-être peut-être l'ajouter à votre fichier .bstrucc):
initramfs-extract() {
local target=$1
local offset=$(binwalk -y gzip $1 | awk '$3 ~ /gzip/ { print $1; exit }')
shift
dd if=$target bs=$offset skip=1 | zcat | cpio -id --no-absolute-filenames $@
}
Le code est basé sur la réponse de Marc, mais cela est nettement plus rapide puisque Binwalk ne recherchera que des fichiers GZIP. Vous pouvez l'invoquer, comme ceci:
$ initramfs-extract /boot/initrd.img -v
Vous aurez besoin de binwalk
installé pour le faire fonctionner.