{"id":356,"date":"2025-05-14T20:49:16","date_gmt":"2025-05-14T20:49:16","guid":{"rendered":"https:\/\/tolva.fr\/?p=356"},"modified":"2025-05-14T20:49:16","modified_gmt":"2025-05-14T20:49:16","slug":"comment-magisk-modifie-init_boot-img","status":"publish","type":"post","link":"https:\/\/tolva.fr\/index.php\/2025\/05\/14\/comment-magisk-modifie-init_boot-img\/","title":{"rendered":"Comment Magisk modifie init_boot.img ?"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Dans les articles pr\u00e9c\u00e9dents, nous avons vu comment utiliser Magisk, explor\u00e9 le contenu d&rsquo;une mise \u00e0 jour Android puis l&rsquo;on s&rsquo;est fait une id\u00e9e de la d\u00e9marche suivie par Magisk pour fournir des droits <em>root<\/em> \u00e0 une application arbitraire.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On sait que rooter un t\u00e9l\u00e9phone avec Magisk implique une modification d&rsquo;une partition (<code>init_boot<\/code> dans notre cas).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mais comment l&rsquo;application Magisk r\u00e9alise-t-elle ces modifications ?<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Modification de l&rsquo;<code>init_boot.img<\/code> par Magisk<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Lorsque l&rsquo;on patche l&rsquo;image <code>init_boot.img<\/code> avec Magisk, les messages suivants sont affich\u00e9s :<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"486\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/05\/android_magisk_patch_4-486x1080.png\" alt=\"\" class=\"wp-image-357\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/05\/android_magisk_patch_4-486x1080.png 486w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/05\/android_magisk_patch_4-135x300.png 135w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/05\/android_magisk_patch_4-768x1707.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/05\/android_magisk_patch_4-691x1536.png 691w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/05\/android_magisk_patch_4-922x2048.png 922w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/05\/android_magisk_patch_4.png 1080w\" sizes=\"auto, (max-width: 486px) 100vw, 486px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Partons de ces messages pour d\u00e9bobiner la pelote de laine.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Les deux seules occurrences du message \u00ab\u00a0Unpacking boot image\u00a0\u00bb se trouvent dans les scripts boot_patch.sh et uninstaller.sh.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ce dernier ne contient toutefois pas le message \u00ab\u00a0Repacking boot image\u00a0\u00bb, contrairement \u00e0 boot_patch.sh, si bien que c&rsquo;est le script boot_patch.sh qui va nous int\u00e9resser.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Notons que ce script commence par un commentaire r\u00e9capitulant les r\u00f4les des diff\u00e9rents utilitaires Magisk, ce qui est tout \u00e0 fait appr\u00e9ciable :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># File name          Type      Description\n#\n# boot_patch.sh      script    A script to patch boot image for Magisk.\n#                  (this file) The script will use files in its same\n#                              directory to complete the patching process.\n# util_functions.sh  script    A script which hosts all functions required\n#                              for this script to work properly.\n# magiskinit         binary    The binary to replace \/init.\n# magisk             binary    The magisk binary.\n# magiskboot         binary    A tool to manipulate boot images.\n# init-ld            binary    The library that will be LD_PRELOAD of \/init\n# stub.apk           binary    The stub Magisk app to embed into ramdisk.\n# chromeos           folder    This folder includes the utility and keys to sign\n#                  (optional)  chromeos boot images. Only used for Pixel C.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Notons d&rsquo;abord que le premier argument, <code>$1<\/code>, est le chemin du fichier \u00e0 patcher :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>BOOTIMAGE=\"$1\"\n&#91; -e \"$BOOTIMAGE\" ] || abort \"$BOOTIMAGE does not exist!\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On unpack ensuite le bootimage avec <code>magiskboot<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#########\n# Unpack\n#########\n\nCHROMEOS=false\n\nui_print \"- Unpacking boot image\"\n.\/magiskboot unpack \"$BOOTIMAGE\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Le commentaire ci-dessus nous dit que <code>magiskboot<\/code> est un \u00ab\u00a0tool to manipulate boot images\u00a0\u00bb. Mais encore ?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Regardons le <code>help<\/code> de <code>magiskboot<\/code> pour avoir des pr\u00e9cisions. Le texte pondu par <code>magiskboot help<\/code> \u00e9tant assez long, nous ne retiendrons que la liste des commandes propos\u00e9es :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>unpack bootimg<\/code> : extrait les diff\u00e9rents composant du fichier <code>bootimg<\/code><\/li>\n\n\n\n<li><code>repack origbootimg outbootimg<\/code> : recr\u00e9\u00e9 un fichier <code>outbootimg<\/code> \u00e0 partir des \u00e9l\u00e9ments de <code>origbootimg<\/code><\/li>\n\n\n\n<li><code>verify bootimg<\/code> : v\u00e9rifie la signature de <code>bootimg<\/code>, retourne 0 (succ\u00e8s) ou 1 (\u00e9chec)<\/li>\n\n\n\n<li><code>sign bootimg<\/code> : signe <code>bootimg<\/code><\/li>\n\n\n\n<li><code>extract payload.bin partition outfile<\/code> : extrait la partition <code>partition<\/code> du fichier <code>payload.bin<\/code>, dans le fichier <code>outfile<\/code><\/li>\n\n\n\n<li><code>hexpatch file hexpattern1 hexpattern2<\/code> : recherche le motif <code>hexpattern1<\/code> dans <code>file<\/code> et le remplace par <code>hexpattern2<\/code><\/li>\n\n\n\n<li><code>cpio incpio commands<\/code> : ex\u00e9cute la sequence de commandes cpio <code>commands<\/code> sur le fichier <code>incpio<\/code><\/li>\n\n\n\n<li><code>dtb file action<\/code> : r\u00e9alise des actions en lien avec le dtb, ie le <em>device tree blob<\/em><\/li>\n\n\n\n<li><code>split file<\/code> : splitte un fichier .dtb<\/li>\n\n\n\n<li><code>compress=format infile outfile<\/code> : compresse un fichier<\/li>\n\n\n\n<li><code>decompress infil outfile<\/code> : d\u00e9compresse un fichier<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">La commande <code>magiskboot unpack \"$BOOTIMAGE\"<\/code> r\u00e9alise donc l&rsquo;extraction de l&rsquo;<code>init_boot.img<\/code>\u2026comme le commentaire le laissait penser.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Que ce passe-t-il dans la suite du script ?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Si un fichier <code>ramdisk.cpio<\/code> est pr\u00e9sent, le script teste sa d\u00e9compression avec <code>magiskboot cpio ramdisk.cpio test<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>###################\n# Ramdisk Restores\n###################\n\n# Test patch status and do restore\nui_print \"- Checking ramdisk status\"\nif &#91; -e ramdisk.cpio ]; then\n  .\/magiskboot cpio ramdisk.cpio test\n  STATUS=$?\n  SKIP_BACKUP=\"\"\nelse\n  # Stock A only legacy SAR, or some Android 13 GKIs\n  STATUS=0\n  SKIP_BACKUP=\"#\"\nfi<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">La valeur de retour de cette commande est soit 0 (cas nominal), soit 1 (ramdisk.cpio patch\u00e9 avec Magisk), soit 2 (format non support\u00e9), soit 4 (ramdisk.cpio Sony).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dans le cas normal, l&rsquo;<code>init_boot.img<\/code> est copi\u00e9 dans <code>stock_boot.img<\/code> et le <code>ramdisk.cpio<\/code> est copi\u00e9 dans <code>ramdisk.cpio.orig<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>case $STATUS in\n  0 )\n    # Stock boot\n    ui_print \"- Stock boot image detected\"\n    SHA1=$(.\/magiskboot sha1 \"$BOOTIMAGE\" 2&gt;\/dev\/null)\n    cat $BOOTIMAGE &gt; stock_boot.img\n    cp -af ramdisk.cpio ramdisk.cpio.orig 2&gt;\/dev\/null\n    ;;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">le cas d&rsquo;un ramdisk.cpio patch\u00e9 avec Magisk, est g\u00e9r\u00e9 diff\u00e9remment :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  1 )\n    # Magisk patched\n    ui_print \"- Magisk patched boot image detected\"\n    .\/magiskboot cpio ramdisk.cpio \\\n    \"extract .backup\/.magisk config.orig\" \\\n    \"restore\"\n    cp -af ramdisk.cpio ramdisk.cpio.orig\n    rm -f stock_boot.img\n    ;;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">enfin en cas d&rsquo;echec l&rsquo;ex\u00e9cution s&rsquo;arr\u00eate :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  2 )\n    # Unsupported\n    ui_print \"! Boot image patched by unsupported programs\"\n    abort \"! Please restore back to stock boot image\"\n    ;;\nesac<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Durant l&rsquo;\u00e9tape suivante, le script compresse les fichiers <code>magisk<\/code>, <code>stub.apk<\/code> et <code>init-ld<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#################\n# Ramdisk Patches\n##################\n\nui_print \"- Patching ramdisk\"\n\n$BOOTMODE &amp;&amp; &#91; -z \"$PREINITDEVICE\" ] &amp;&amp; PREINITDEVICE=$(.\/magisk --preinit-device)\n\n# Compress to save precious ramdisk space\n.\/magiskboot compress=xz magisk magisk.xz\n.\/magiskboot compress=xz stub.apk stub.xz\n.\/magiskboot compress=xz init-ld init-ld.xz<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Un fichier <code>config<\/code> contenant divers \u00e9l\u00e9ments de configuration est cr\u00e9\u00e9 :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"KEEPVERITY=$KEEPVERITY\" &gt; config\necho \"KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT\" &gt;&gt; config\necho \"RECOVERYMODE=$RECOVERYMODE\" &gt;&gt; config\nif &#91; -n \"$PREINITDEVICE\" ]; then\n  ui_print \"- Pre-init storage partition: $PREINITDEVICE\"\n  echo \"PREINITDEVICE=$PREINITDEVICE\" &gt;&gt; config\nfi\n&#91; -n \"$SHA1\" ] &amp;&amp; echo \"SHA1=$SHA1\" &gt;&gt; config<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ensuite, le <code>ramdisk.cpio<\/code> est patch\u00e9 :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/magiskboot cpio ramdisk.cpio \\\n\"add 0750 init magiskinit\" \\\n\"mkdir 0750 overlay.d\" \\\n\"mkdir 0750 overlay.d\/sbin\" \\\n\"add 0644 overlay.d\/sbin\/magisk.xz magisk.xz\" \\\n\"add 0644 overlay.d\/sbin\/stub.xz stub.xz\" \\\n\"add 0644 overlay.d\/sbin\/init-ld.xz init-ld.xz\" \\\n\"patch\" \\\n\"$SKIP_BACKUP backup ramdisk.cpio.orig\" \\\n\"mkdir 000 .backup\" \\\n\"add 000 .backup\/.magisk config\" \\\n|| abort \"! Unable to patch ramdisk\"\n\nrm -f ramdisk.cpio.orig config *.xz<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Dans l&rsquo;\u00e9tape suivante, fstab est patch\u00e9 :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#################\n# Binary Patches\n#################\n\nfor dt in dtb kernel_dtb extra; do\n  if &#91; -f $dt ]; then\n    if ! .\/magiskboot dtb $dt test; then\n      ui_print \"! Boot image $dt was patched by old (unsupported) Magisk\"\n      abort \"! Please try again with *unpatched* boot image\"\n    fi\n    if .\/magiskboot dtb $dt patch; then\n      ui_print \"- Patch fstab in boot image $dt\"\n    fi\n  fi\ndone<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Lorsqu&rsquo;un noyau est pr\u00e9sent dans le fichier fourni (ce qui n&rsquo;est pas le cas avec un <code>init_boot.img<\/code>), celui-ci est patch\u00e9 si n\u00e9cessaire :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if &#91; -f kernel ]; then\n  PATCHEDKERNEL=false\n  # Remove Samsung RKP\n  .\/magiskboot hexpatch kernel \\\n  49010054011440B93FA00F71E9000054010840B93FA00F7189000054001840B91FA00F7188010054 \\\n  A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054 \\\n  &amp;&amp; PATCHEDKERNEL=true\n\n  # Remove Samsung defex\n  # Before: &#91;mov w2, #-221]   (-__NR_execve)\n  # After:  &#91;mov w2, #-32768]\n  .\/magiskboot hexpatch kernel 821B8012 E2FF8F12 &amp;&amp; PATCHEDKERNEL=true\n\n  # Disable Samsung PROCA\n  # proca_config -&gt; proca_magisk\n  .\/magiskboot hexpatch kernel \\\n  70726F63615F636F6E66696700 \\\n  70726F63615F6D616769736B00 \\\n  &amp;&amp; PATCHEDKERNEL=true\n\n  # Force kernel to load rootfs for legacy SAR devices\n  # skip_initramfs -&gt; want_initramfs\n  $LEGACYSAR &amp;&amp; .\/magiskboot hexpatch kernel \\\n  736B69705F696E697472616D667300 \\\n  77616E745F696E697472616D667300 \\\n  &amp;&amp; PATCHEDKERNEL=true\n\n  # If the kernel doesn't need to be patched at all,\n  # keep raw kernel to avoid bootloops on some weird devices\n  $PATCHEDKERNEL || rm -f kernel\nfi<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enfin l&rsquo;<code>init_boot.img<\/code> est reconstruit avec le ramdisk modifi\u00e9 :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#################\n# Repack &amp; Flash\n#################\n\nui_print \"- Repacking boot image\"\n.\/magiskboot repack \"$BOOTIMAGE\" || abort \"! Unable to repack boot image\"\n\n# Sign chromeos boot\n$CHROMEOS &amp;&amp; sign_chromeos\n\n# Restore the original boot partition path\n&#91; -e \"$BOOTNAND\" ] &amp;&amp; BOOTIMAGE=\"$BOOTNAND\"\n\n# Reset any error code\ntrue<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Conclusions<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Le script boot_patch.sh lanc\u00e9 par l&rsquo;application Magisk modifie l&rsquo;init_boot.img :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ajout de l&rsquo;init sauce Magisk<\/li>\n\n\n\n<li>Ajout d&rsquo;un r\u00e9pertoire overlay.d contenant notamment magisk.xz, stub.xz<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Dans les articles pr\u00e9c\u00e9dents, nous avons vu comment utiliser Magisk, explor\u00e9 le contenu d&rsquo;une mise \u00e0 jour Android puis l&rsquo;on s&rsquo;est fait une id\u00e9e de la d\u00e9marche suivie par Magisk pour fournir des droits root \u00e0 une application arbitraire. On sait que rooter un t\u00e9l\u00e9phone avec Magisk implique une modification d&rsquo;une partition (init_boot dans notre [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-356","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts\/356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/comments?post=356"}],"version-history":[{"count":1,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts\/356\/revisions"}],"predecessor-version":[{"id":358,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts\/356\/revisions\/358"}],"wp:attachment":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/media?parent=356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/categories?post=356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/tags?post=356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}