Korzystam z kompilacji live Debiana do pracy na systemie startowym. Pod koniec procesu otrzymuję typowe pliki używane do rozruchu systemu na żywo: plik squashfs, niektóre moduły GRUB i pliki konfiguracyjne oraz plik initrd.img.
Mogę dobrze uruchomić przy użyciu tych plików, przekazując initrd do jądra przez
initrd=/path/to/my/initrd.img
w wierszu polecenia bootloadera. Ale kiedy próbuję zbadać zawartość mojego obrazu initrd, tak:
$file initrd.img
initrd.img: ASCII cpio archive (SVR4 with no CRC)
$mkdir initTree && cd initTree
$cpio -idv < ../initrd.img
otrzymane drzewo plików wygląda następująco:
$tree --charset=ASCII
.
`-- kernel
`-- x86
`-- microcode
`-- GenuineIntel.bin
Gdzie jest rzeczywiste drzewo systemu plików, z typowym / bin, / etc, / sbin ... zawierające rzeczywiste pliki używane podczas uruchamiania?
Odpowiedzi:
Podana metoda pomijania bloku cpio nie działa niezawodnie. To dlatego, że obrazy initrd, które sobie robiłem, nie łączyły obu archiwów na granicy 512 bajtów.
Zamiast tego wykonaj następujące czynności:
Użyj ostatniego numeru (21136), który nie jest dla mnie na granicy 512 bajtów:
źródło
cd
do katalogu, w którym zostały wyodrębnione archiwum cpio, uruchomfind | cpio -H newc -o > /tmp/my_archive.cpio
, a następnie gzip gogzip /tmp/my_archive.cpio
wreszcie złączyć go z obrazem z mikrokodu, gdybyś miał jeden:cat my_microcode_image.cpio /tmp/my_archive.cpio.gz > mynewinitrd.img
. Jeśli nie masz obrazu mikrokodu, możesz po prostu użyć swojego pliku spakowanego gzipem, tak jak jest to w bootloaderzecpio -i
, zamiastcpio -tdv | head
.Jeśli wiesz, że twoje
initrd.img
składa się z nieskompresowanego archiwum cpio, a następnie archiwum cpio skompresowanego gz, możesz użyć następującego polecenia, aby wyodrębnić wszystkie pliki (z obu archiwów) do bieżącego katalogu roboczego (przetestowanego w bash):Polecenie powyżej linii przekazuje zawartość
initrd.img
jako standardowe wejście w podpowłoce, który wykonuje dwa poleceniacpio -id
izcat | cpio -id
kolejno. Pierwsze polecenie (cpio -id
) kończy się po odczytaniu wszystkich danych należących do pierwszego archiwum CPIO. Pozostała zawartość jest następnie przekazywana dozcat | cpio -id
dekompresji i rozpakowywania drugiego archiwum.źródło
Okazuje się, że initrd wygenerowany przez live-build Debiana (i ku mojemu zaskoczeniu, zaakceptowany przez jądro) jest w rzeczywistości połączeniem dwóch obrazów:
Po wypakowaniu oryginalnego pliku initrd.img, bezpośrednio z wyjścia kompilacji na żywo, otrzymałem ten wynik:
Co oznacza, że ekstrakcja procesora zakończyła się po przeanalizowaniu 896 bloków po 512 bajtów każdy. Ale oryginalny initrd.img był znacznie większy niż 896 * 512 = 458752B = 448 KB:
Tak więc rzeczywisty obraz initrd, którego szukałem, został dołączony zaraz po pierwszym archiwum CPIO (tym, które zawiera aktualizacje mikrokodu) i można było uzyskać do niego dostęp za pomocą dd:
źródło
Możesz używać
unmkinitramfs
z initramfs-tools> = 0.126, która jest dołączana od Debiana 9 (stretch) i Ubuntu 18.04 (bionic).źródło
Opierając się na pomyśle podanym w odpowiedzi na @ woolpool, napisałem funkcję rekurencyjną, która będzie działać dla każdego archiwum CPIO niezależnie od ułożenia połączonych danych i nie wymaga żadnych specjalnych narzędzi, takich jak binwalk. Na przykład moje mkinitramfs produkowało plik cpio; cpio; gzip. Działa poprzez wyodrębnienie każdej części połączonego pliku initrd, zapisanie reszty w pliku tymczasowym, a następnie za pomocą programu „file”, aby zdecydować, co zrobić z następną częścią.
Aby użyć wpisz: uncpio initrdfilename
źródło
Jeśli musisz często wykonywać to zadanie, możesz utworzyć małą funkcję bash, taką jak poniżej (i być może dodać ją do swojego .bashrc):
Kod oparty jest na odpowiedzi Marca, ale jest znacznie szybszy, ponieważ binwalk będzie szukał tylko plików gzip. Możesz go wywołać w następujący sposób:
Musisz go
binwalk
zainstalować, aby działał.źródło