{"id":451,"date":"2026-11-05T19:40:16","date_gmt":"2026-11-05T19:40:16","guid":{"rendered":"https:\/\/tolva.fr\/?p=451"},"modified":"2026-11-05T19:40:16","modified_gmt":"2026-11-05T19:40:16","slug":"le-dossier-securise-dandroid","status":"publish","type":"post","link":"https:\/\/tolva.fr\/index.php\/2026\/11\/05\/le-dossier-securise-dandroid\/","title":{"rendered":"Le dossier s\u00e9curis\u00e9 d&rsquo;Android"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/support.google.com\/files\/answer\/9935264?hl=fr\" data-type=\"link\" data-id=\"https:\/\/support.google.com\/files\/answer\/9935264?hl=fr\">Le dossier s\u00e9curis\u00e9<\/a> est une fonctionnalit\u00e9 pr\u00e9sente sur les t\u00e9l\u00e9phones Android permettant de dissimuler des fichiers dans un emplacement dont l&rsquo;acc\u00e8s est prot\u00e9g\u00e9 par un code PIN ou un sch\u00e9ma.<\/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\/2026\/11\/1_safefolder-486x1080.png\" alt=\"\" class=\"wp-image-452\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2026\/11\/1_safefolder-486x1080.png 486w, https:\/\/tolva.fr\/wp-content\/uploads\/2026\/11\/1_safefolder-135x300.png 135w, https:\/\/tolva.fr\/wp-content\/uploads\/2026\/11\/1_safefolder-768x1707.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2026\/11\/1_safefolder-691x1536.png 691w, https:\/\/tolva.fr\/wp-content\/uploads\/2026\/11\/1_safefolder-922x2048.png 922w, https:\/\/tolva.fr\/wp-content\/uploads\/2026\/11\/1_safefolder.png 1080w\" sizes=\"auto, (max-width: 486px) 100vw, 486px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">O\u00f9 les fichiers du dossier s\u00e9curis\u00e9 sont-ils stock\u00e9s ?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">La premi\u00e8re \u00e9tape est de d\u00e9terminer la localisation physique du dossier s\u00e9curis\u00e9. \u00c9num\u00e9rons les fichiers de plus de 500Mo pr\u00e9sents sur le t\u00e9l\u00e9phone :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>lynx:\/ # find \/ -type f -size +500M 2&gt;\/dev\/null\n\/data\/user\/0\/com.android.virtualization.terminal\/files\/linux\/root_part\n\/data\/data\/com.android.virtualization.terminal\/files\/linux\/root_part\n\/data\/gsi\/ota\/product_b-cow-img.img.0000\n\/data_mirror\/data_ce\/null\/0\/com.android.virtualization.terminal\/files\/linux\/root_part<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Maintenant, cr\u00e9ons dans \/data\/media\/0\/Download un fichier constitu\u00e9 d&rsquo;environ 500 millions de &lsquo;a&rsquo; :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>lynx:\/data\/media\/0\/Download # dd if=\/dev\/zero bs=16M count=32 2&gt;\/dev\/null | tr '\\0' 'a' &gt; a.txt\nlynx:\/data\/media\/0\/Download # chmod 777 a.txt\nlynx:\/data\/media\/0\/Download # ls -l a.txt\n-rwxrwxrwx 1 root media_rw 536870912 2026-10-13 17:36 a.txt\nlynx:\/data\/media\/0\/Download # ls -lh a.txt\n-rwxrwxrwx 1 root media_rw 512M 2026-10-13 17:36 a.txt\nlynx:\/data\/media\/0\/Download # md5sum a.txt\n31e4d9c6d74cd592b78f77f72965d6ab  a.txt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Relan\u00e7ons la recherche :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>lynx:\/data\/media\/0\/Download # find \/ -type f -size +500M 2&gt;\/dev\/null \n\/storage\/emulated\/0\/Download\/a.txt\n\/mnt\/pass_through\/0\/emulated\/0\/Download\/a.txt\n\/mnt\/androidwritable\/0\/emulated\/0\/Download\/a.txt\n\/mnt\/installer\/0\/emulated\/0\/Download\/a.txt\n\/mnt\/user\/0\/emulated\/0\/Download\/a.txt\n\/data\/media\/0\/Download\/a.txt\n\/data\/user\/0\/com.android.virtualization.terminal\/files\/linux\/root_part\n\/data\/data\/com.android.virtualization.terminal\/files\/linux\/root_part\n\/data\/gsi\/ota\/product_b-cow-img.img.0000\n\/data_mirror\/data_ce\/null\/0\/com.android.virtualization.terminal\/files\/linux\/root_part<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Cette recherche identifie sans ambigu\u00eft\u00e9 notre fichier <code>a.txt<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">D\u00e9pla\u00e7ons-le maintenant dans le dossier s\u00e9curis\u00e9. Le fichier r\u00e9sultant sera probablement chiffr\u00e9 et aura une taille normalement sup\u00e9rieure au fichier clair.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En relan\u00e7ant <code>find<\/code> une nouvelle fois, nous n&rsquo;allons plus voir <code>a.txt<\/code>, mais allons voir appara\u00eetre un nouveau fichier qui sera <code>a.txt<\/code> dans le dossier s\u00e9curis\u00e9 :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>lynx:\/ # find \/ -type f -size +500M 2&gt;\/dev\/null \n\/data\/user\/0\/com.android.virtualization.terminal\/files\/linux\/root_part\n\/data\/user\/0\/com.google.android.apps.nbu.files\/files\/.FilesByGoogle\/a.txt\n\/data\/data\/com.android.virtualization.terminal\/files\/linux\/root_part\n\/data\/data\/com.google.android.apps.nbu.files\/files\/.FilesByGoogle\/a.txt\n\/data_mirror\/data_ce\/null\/0\/com.android.virtualization.terminal\/files\/linux\/root_part\n\/data_mirror\/data_ce\/null\/0\/com.google.android.apps.nbu.files\/files\/.FilesByGoogle\/a.txt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Recalculons le hach\u00e9 du fichier <code>a.txt<\/code> pr\u00e9sent dans le dossier s\u00e9curis\u00e9 :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>lynx:\/ # ls -l \/data\/data\/com.google.android.apps.nbu.files\/files\/.FilesByGoogle\/a.txt\n-rw------- 1 u0_a152 u0_a152 536870912 2026-10-14 00:02 \/data\/data\/com.google.android.apps.nbu.files\/files\/.FilesByGoogle\/a.txt\nlynx:\/ # md5sum \/data\/data\/com.google.android.apps.nbu.files\/files\/.FilesByGoogle\/a.txt\n31e4d9c6d74cd592b78f77f72965d6ab  \/data\/data\/com.google.android.apps.nbu.files\/files\/.FilesByGoogle\/a.txt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">C&rsquo;est le hach\u00e9 du fichier en clair ! C&rsquo;est une surprise car l&rsquo;on pouvait imaginer que les fichiers d\u00e9plac\u00e9s dans le dossier s\u00e9curis\u00e9 y soient chiffr\u00e9s.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Red\u00e9marrons le t\u00e9l\u00e9phone et recherchons maintenant les fichiers de plus de 500 Mo, mais AVANT de d\u00e9verrouiller le t\u00e9l\u00e9phone :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>1|lynx:\/ # find \/ -type f -size +500M -exec ls -l {} \\; 2&gt;\/dev\/null\n-rw------- 1 u0_a287 u0_a287 112117940224 2026-10-03 00:27 \/data\/user\/0\/du138wAAAAADPUh3FVAZLIOdWc_ENZiuCVge453wRVY8vvFIF_qquihAEXhb2dh1m9cXeupIX4Y\/3p65BgAAAABciauWOY0P98nR-TWuoyno\/5_mUvQAAAACygXiwUHlOY1RR-h6qhuPC\/v5HKLAAAAAD4KcFDgbz6-8WtQc6aU0mU\n-rw------- 1 u0_a152 u0_a152 536870912 2026-10-14 00:02 \/data\/user\/0\/2IWWHQAAAACV0A7Iqks0v7u4pCNyeYjgSVReZOFcWtZfp27PTKmE_xzdEktNzJ-JtIL91VUTQ8U\/5ozATwAAAAAjRgE9_ZBOnzcXokYTVtSL\/xmqMnQAAAABYP5Z_Wnd4GPsSVtWgN7ur\/qQ5TuAAAAADC21R90w_CmiR59zBPZ-Ch\n-rw------- 1 u0_a287 u0_a287 112117940224 2026-10-03 00:27 \/data\/data\/du138wAAAAADPUh3FVAZLIOdWc_ENZiuCVge453wRVY8vvFIF_qquihAEXhb2dh1m9cXeupIX4Y\/3p65BgAAAABciauWOY0P98nR-TWuoyno\/5_mUvQAAAACygXiwUHlOY1RR-h6qhuPC\/v5HKLAAAAAD4KcFDgbz6-8WtQc6aU0mU\n-rw------- 1 u0_a152 u0_a152 536870912 2026-10-14 00:02 \/data\/data\/2IWWHQAAAACV0A7Iqks0v7u4pCNyeYjgSVReZOFcWtZfp27PTKmE_xzdEktNzJ-JtIL91VUTQ8U\/5ozATwAAAAAjRgE9_ZBOnzcXokYTVtSL\/xmqMnQAAAABYP5Z_Wnd4GPsSVtWgN7ur\/qQ5TuAAAAADC21R90w_CmiR59zBPZ-Ch\n-rw------- 1 u0_a287 u0_a287 112117940224 2026-10-03 00:27 \/data_mirror\/data_ce\/null\/0\/du138wAAAAADPUh3FVAZLIOdWc_ENZiuCVge453wRVY8vvFIF_qquihAEXhb2dh1m9cXeupIX4Y\/3p65BgAAAABciauWOY0P98nR-TWuoyno\/5_mUvQAAAACygXiwUHlOY1RR-h6qhuPC\/v5HKLAAAAAD4KcFDgbz6-8WtQc6aU0mU\n-rw------- 1 u0_a152 u0_a152 536870912 2026-10-14 00:02 \/data_mirror\/data_ce\/null\/0\/2IWWHQAAAACV0A7Iqks0v7u4pCNyeYjgSVReZOFcWtZfp27PTKmE_xzdEktNzJ-JtIL91VUTQ8U\/5ozATwAAAAAjRgE9_ZBOnzcXokYTVtSL\/xmqMnQAAAABYP5Z_Wnd4GPsSVtWgN7ur\/qQ5TuAAAAADC21R90w_CmiR59zBPZ-Ch<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Le fichier est bien pr\u00e9sent (c&rsquo;est le fichier de 536870912 octets), sous une forme chiffr\u00e9e. Ce m\u00e9canisme de chiffrement n&rsquo;a toutefois rien \u00e0 voir avec la fonctionnalit\u00e9 de dossier s\u00e9curis\u00e9 : il s&rsquo;agit <a href=\"https:\/\/blog.quarkslab.com\/android-data-encryption-in-depth.html\" data-type=\"link\" data-id=\"https:\/\/blog.quarkslab.com\/android-data-encryption-in-depth.html\">du chiffrement FBE mis en oeuvre par Android lui-m\u00eame<\/a>. <br><br>Nous savons que l&rsquo;application impl\u00e9mentant le dossier s\u00e9curis\u00e9 est Files by Google, dont le nom de package est com.google.android.apps.nbu.files.<br><br>Quel est l&#8217;emplacement de l&rsquo;apk correspondant ?<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>lynx:\/ # pm list packages -f | grep 'nbu.files'\npackage:\/data\/app\/~~13rQB2-z-UJSzQgCOBkBEw==\/com.google.android.apps.nbu.files-lBnlganWVRDi9OsMDpPctw==\/base.apk=com.google.android.apps.nbu.files<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">R\u00e9cup\u00e9rons-le, et \u00e9tudions-le statiquement et dynamiquement.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pour cela, recherchons des appels \u00e0 des fonctions et api cryptographiques usuelles. Il est plausible que le code PIN saisi soit utilis\u00e9 dans une op\u00e9ration de d\u00e9rivation de clef, qui risque de faire intervenir un HMAC. Une piste naturelle est donc de tracer les m\u00e9thodes dont le nom contient le mot \u00ab\u00a0HMAC\u00a0\u00bb :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bingo, un appel au constructeur de <code>BasePBKDF2WithHmacSHA1<\/code> est appel\u00e9 :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>frida-trace -U -f com.google.android.apps.nbu.files -j '*Hmac*!*'\n(...)\n 12378 ms  PBEPBKDF2$PBKDF2WithHmacSHA1UTF8.$init()\n 12380 ms     | PBEPBKDF2$BasePBKDF2WithHmacSHA1.$init(\"PBKDF2WithHmacSHA1\", 5)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Si \u00e0 la place du mot-cl\u00e9 \u00ab\u00a0Hmac\u00a0\u00bb on utilise le mot-cl\u00e9 \u00ab\u00a0symmetric\u00a0\u00bb, on trouve pas mal de choses int\u00e9ressantes. En restreignant un peu, on tombe sur l&rsquo;appel \u00e0 une fonction <code>convertPassword<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">qui re\u00e7oit le code PIN utilis\u00e9 (2718, caract\u00e8res qui ont pour valeur ascii (<code>0x32, 0x37, 0x31, 0x38<\/code>), soit (50, 55, 49, 56) en d\u00e9cimal), et sur un tableau de 32 octets qui pourrait tout \u00e0 fait \u00eatre une cl\u00e9 sym\u00e9trique :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>frida-trace -U -f com.google.android.apps.nbu.files -j 'com.android.org.bouncycastle.jcajce.provider.symmetric*!*'\n(...)\n           \/* TID 0x1d1 *\/\n  8674 ms  PBEPBKDF2$PBKDF2WithHmacSHA1UTF8.$init()\n  8678 ms     | PBEPBKDF2$BasePBKDF2WithHmacSHA1.$init(\"PBKDF2WithHmacSHA1\", 5)\n  8679 ms     |    | PBEPBKDF2$BasePBKDF2.$init(\"PBKDF2WithHmacSHA1\", 5, 1, null)\n  8680 ms     |    |    | PBEPBKDF2$BasePBKDF2.$init(\"PBKDF2WithHmacSHA1\", 5, 1)\n  8681 ms     |    |    |    | PBEPBKDF2$BasePBKDF2.$init(\"PBKDF2WithHmacSHA1\", 5, 1, 0, 0)\n  8686 ms     |    |    |    |    | BaseSecretKeyFactory.$init(\"PBKDF2WithHmacSHA1\", \"&lt;instance: com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier&gt;\")\n  8698 ms  PBEPBKDF2$BasePBKDF2.engineGenerateSecret(\"&lt;instance: java.security.spec.KeySpec, $className: javax.crypto.spec.PBEKeySpec&gt;\")\n  8702 ms     | PBE$Util.makePBEMacParameters(\"&lt;instance: javax.crypto.spec.PBEKeySpec&gt;\", 5, 1, 256)\n  8702 ms     |    | PBE$Util.makePBEGenerator(5, 1)\n  8706 ms     |    | &lt;= \"&lt;instance: com.android.org.bouncycastle.crypto.PBEParametersGenerator, $className: com.android.org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator&gt;\"\n  8707 ms     |    | PBE$Util.convertPassword(5, \"&lt;instance: javax.crypto.spec.PBEKeySpec&gt;\")\n  8708 ms     |    | &lt;= &#91;50,55,49,56]\n  9400 ms     | &lt;= \"&lt;instance: com.android.org.bouncycastle.crypto.CipherParameters, $className: com.android.org.bouncycastle.crypto.params.KeyParameter&gt;\"\n  9401 ms     | BCPBEKey.$init(\"PBKDF2WithHmacSHA1\", \"&lt;instance: com.android.org.bouncycastle.asn1.ASN1ObjectIdentifier&gt;\", 5, 1, 256, -1, \"&lt;instance: javax.crypto.spec.PBEKeySpec&gt;\", \"&lt;instance: com.android.org.bouncycastle.crypto.CipherParameters, $className: com.android.org.bouncycastle.crypto.params.KeyParameter&gt;\")\n  9401 ms  &lt;= \"&lt;instance: javax.crypto.SecretKey, $className: com.android.org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey&gt;\"\n  9401 ms  BCPBEKey.getEncoded()\n  9401 ms     | BCPBEKey.checkDestroyed(\"&lt;instance: javax.security.auth.Destroyable, $className: com.android.org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey&gt;\")\n  9401 ms     |    | BCPBEKey.isDestroyed()\n  9401 ms     |    | &lt;= false\n  9402 ms  &lt;= &#91;-123,-52,-68,-30,-92,-106,-21,124,30,-58,53,59,24,-59,99,-114,34,-17,-8,79,103,3,-13,28,13,-9,99,30,109,-74,35,-13]<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Si l&rsquo;on trace ensuite les appels aux m\u00e9thodes des packages <code>javax.crypto<\/code>, on observe un appel \u00e0 un constructeur de <code>PBEKeySpec<\/code>, auquel est pass\u00e9 en argument :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>le code PIN,<\/li>\n\n\n\n<li>un sel de 256 octets,<\/li>\n\n\n\n<li>un nombre d&rsquo;it\u00e9rations (\u00e9gal \u00e0 10000),<\/li>\n\n\n\n<li>la taille de la cl\u00e9 \u00e0 produire (256 bits)<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>frida-trace -U -f com.google.android.apps.nbu.files -j 'javax.crypto*!*'\n\n           \/* TID 0x426 *\/\n  7445 ms  SecretKeyFactory.getInstance(\"PBKDF2WithHmacSHA1\")\n  7445 ms     | SecretKeyFactory.$init(\"PBKDF2WithHmacSHA1\")\n  7446 ms     |    | SecretKeyFactory.nextSpi(null)\n  7447 ms     |    |    | SecretKeyFactorySpi.$init()\n  7447 ms     |    | &lt;= \"&lt;instance: javax.crypto.SecretKeyFactorySpi, $className: com.android.org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2$PBKDF2WithHmacSHA1UTF8&gt;\"\n  7449 ms  &lt;= \"&lt;instance: javax.crypto.SecretKeyFactory&gt;\"\n  7449 ms  PBEKeySpec.$init(&#91;\"2\",\"7\",\"1\",\"8\"], &#91;-68,-49,-9,88,51,-48,-44,73,98,-117,-76,-14,-40,16,-8,-43,-80,-100,-115,41,78,69,-104,0,-30,-13,106,-113,-124,-9,21,1,-67,3,-84,-106,1,15,-49,-44,63,103,-8,-82,-81,-53,80,53,89,-27,-19,28,91,-46,-30,-109,-89,11,-92,-99,5,-52,-44,-102,37,-123,25,6,-73,-126,-32,-12,24,-44,4,-119,99,35,56,15,124,-70,-46,-90,68,-102,-32,105,24,-127,-59,20,104,7,-92,-69,93,104,-30,90,-42,-14,-7,121,114,75,-110,-102,25,-80,-92,71,119,-46,97,-20,-55,102,-87,86,-65,-1,-37,-74,-86,29,96,45,-32,44,86,71,-52,-26,-80,-128,77,7,-70,17,-76,-21,76,24,-84,33,-93,-116,-108,-38,-89,84,114,-68,-101,-79,-74,-94,98,-98,-30,-45,-73,-54,-25,37,-37,-103,-24,86,120,-88,-99,106,95,23,-124,77,-58,-122,-40,36,-32,-100,101,34,-72,96,73,-22,4,104,89,-54,14,-64,81,-60,-125,-98,0,110,18,-107,86,41,-56,119,56,-110,58,122,-43,-46,5,-122,-54,56,48,11,117,-55,48,14,-121,70,8,-60,56,-54,-68,6,89,-100,-14,-77,59,-54,-8,51,-10,119,-9,-52,-86,37,-12,91,76,7,97,39,-79,25,99,1], 10000, 256)\n  7451 ms  SecretKeyFactory.generateSecret(\"&lt;instance: java.security.spec.KeySpec, $className: javax.crypto.spec.PBEKeySpec&gt;\")\n  7451 ms     | PBEKeySpec.getSalt()\n  7451 ms     | &lt;= &#91;-68,-49,-9,88,51,-48,-44,73,98,-117,-76,-14,-40,16,-8,-43,-80,-100,-115,41,78,69,-104,0,-30,-13,106,-113,-124,-9,21,1,-67,3,-84,-106,1,15,-49,-44,63,103,-8,-82,-81,-53,80,53,89,-27,-19,28,91,-46,-30,-109,-89,11,-92,-99,5,-52,-44,-102,37,-123,25,6,-73,-126,-32,-12,24,-44,4,-119,99,35,56,15,124,-70,-46,-90,68,-102,-32,105,24,-127,-59,20,104,7,-92,-69,93,104,-30,90,-42,-14,-7,121,114,75,-110,-102,25,-80,-92,71,119,-46,97,-20,-55,102,-87,86,-65,-1,-37,-74,-86,29,96,45,-32,44,86,71,-52,-26,-80,-128,77,7,-70,17,-76,-21,76,24,-84,33,-93,-116,-108,-38,-89,84,114,-68,-101,-79,-74,-94,98,-98,-30,-45,-73,-54,-25,37,-37,-103,-24,86,120,-88,-99,106,95,23,-124,77,-58,-122,-40,36,-32,-100,101,34,-72,96,73,-22,4,104,89,-54,14,-64,81,-60,-125,-98,0,110,18,-107,86,41,-56,119,56,-110,58,122,-43,-46,5,-122,-54,56,48,11,117,-55,48,14,-121,70,8,-60,56,-54,-68,6,89,-100,-14,-77,59,-54,-8,51,-10,119,-9,-52,-86,37,-12,91,76,7,97,39,-79,25,99,1]\n  7452 ms     | PBEKeySpec.getSalt()\n  7452 ms     | &lt;= &#91;-68,-49,-9,88,51,-48,-44,73,98,-117,-76,-14,-40,16,-8,-43,-80,-100,-115,41,78,69,-104,0,-30,-13,106,-113,-124,-9,21,1,-67,3,-84,-106,1,15,-49,-44,63,103,-8,-82,-81,-53,80,53,89,-27,-19,28,91,-46,-30,-109,-89,11,-92,-99,5,-52,-44,-102,37,-123,25,6,-73,-126,-32,-12,24,-44,4,-119,99,35,56,15,124,-70,-46,-90,68,-102,-32,105,24,-127,-59,20,104,7,-92,-69,93,104,-30,90,-42,-14,-7,121,114,75,-110,-102,25,-80,-92,71,119,-46,97,-20,-55,102,-87,86,-65,-1,-37,-74,-86,29,96,45,-32,44,86,71,-52,-26,-80,-128,77,7,-70,17,-76,-21,76,24,-84,33,-93,-116,-108,-38,-89,84,114,-68,-101,-79,-74,-94,98,-98,-30,-45,-73,-54,-25,37,-37,-103,-24,86,120,-88,-99,106,95,23,-124,77,-58,-122,-40,36,-32,-100,101,34,-72,96,73,-22,4,104,89,-54,14,-64,81,-60,-125,-98,0,110,18,-107,86,41,-56,119,56,-110,58,122,-43,-46,5,-122,-54,56,48,11,117,-55,48,14,-121,70,8,-60,56,-54,-68,6,89,-100,-14,-77,59,-54,-8,51,-10,119,-9,-52,-86,37,-12,91,76,7,97,39,-79,25,99,1]\n  7452 ms     | PBEKeySpec.getIterationCount()\n  7453 ms     | &lt;= 10000\n  7453 ms     | PBEKeySpec.getKeyLength()\n  7453 ms     | &lt;= 256\n  7453 ms     | PBEKeySpec.getPassword()\n  7453 ms     | &lt;= &#91;\"2\",\"7\",\"1\",\"8\"]\n  7453 ms     | PBEKeySpec.getKeyLength()\n  7453 ms     | &lt;= 256\n  7453 ms     | PBEKeySpec.getPassword()\n  7454 ms     | &lt;= &#91;\"2\",\"7\",\"1\",\"8\"]\n  7454 ms     | PBEKeySpec.getSalt()\n  7454 ms     | &lt;= &#91;-68,-49,-9,88,51,-48,-44,73,98,-117,-76,-14,-40,16,-8,-43,-80,-100,-115,41,78,69,-104,0,-30,-13,106,-113,-124,-9,21,1,-67,3,-84,-106,1,15,-49,-44,63,103,-8,-82,-81,-53,80,53,89,-27,-19,28,91,-46,-30,-109,-89,11,-92,-99,5,-52,-44,-102,37,-123,25,6,-73,-126,-32,-12,24,-44,4,-119,99,35,56,15,124,-70,-46,-90,68,-102,-32,105,24,-127,-59,20,104,7,-92,-69,93,104,-30,90,-42,-14,-7,121,114,75,-110,-102,25,-80,-92,71,119,-46,97,-20,-55,102,-87,86,-65,-1,-37,-74,-86,29,96,45,-32,44,86,71,-52,-26,-80,-128,77,7,-70,17,-76,-21,76,24,-84,33,-93,-116,-108,-38,-89,84,114,-68,-101,-79,-74,-94,98,-98,-30,-45,-73,-54,-25,37,-37,-103,-24,86,120,-88,-99,106,95,23,-124,77,-58,-122,-40,36,-32,-100,101,34,-72,96,73,-22,4,104,89,-54,14,-64,81,-60,-125,-98,0,110,18,-107,86,41,-56,119,56,-110,58,122,-43,-46,5,-122,-54,56,48,11,117,-55,48,14,-121,70,8,-60,56,-54,-68,6,89,-100,-14,-77,59,-54,-8,51,-10,119,-9,-52,-86,37,-12,91,76,7,97,39,-79,25,99,1]\n  7454 ms     | PBEKeySpec.getIterationCount()\n  7455 ms     | &lt;= 10000\n  8056 ms     | PBEKeySpec.getPassword()\n  8056 ms     | &lt;= &#91;\"2\",\"7\",\"1\",\"8\"]\n  8056 ms     | PBEKeySpec.getIterationCount()\n  8056 ms     | &lt;= 10000\n  8056 ms     | PBEKeySpec.getSalt()\n  8056 ms     | &lt;= &#91;-68,-49,-9,88,51,-48,-44,73,98,-117,-76,-14,-40,16,-8,-43,-80,-100,-115,41,78,69,-104,0,-30,-13,106,-113,-124,-9,21,1,-67,3,-84,-106,1,15,-49,-44,63,103,-8,-82,-81,-53,80,53,89,-27,-19,28,91,-46,-30,-109,-89,11,-92,-99,5,-52,-44,-102,37,-123,25,6,-73,-126,-32,-12,24,-44,4,-119,99,35,56,15,124,-70,-46,-90,68,-102,-32,105,24,-127,-59,20,104,7,-92,-69,93,104,-30,90,-42,-14,-7,121,114,75,-110,-102,25,-80,-92,71,119,-46,97,-20,-55,102,-87,86,-65,-1,-37,-74,-86,29,96,45,-32,44,86,71,-52,-26,-80,-128,77,7,-70,17,-76,-21,76,24,-84,33,-93,-116,-108,-38,-89,84,114,-68,-101,-79,-74,-94,98,-98,-30,-45,-73,-54,-25,37,-37,-103,-24,86,120,-88,-99,106,95,23,-124,77,-58,-122,-40,36,-32,-100,101,34,-72,96,73,-22,4,104,89,-54,14,-64,81,-60,-125,-98,0,110,18,-107,86,41,-56,119,56,-110,58,122,-43,-46,5,-122,-54,56,48,11,117,-55,48,14,-121,70,8,-60,56,-54,-68,6,89,-100,-14,-77,59,-54,-8,51,-10,119,-9,-52,-86,37,-12,91,76,7,97,39,-79,25,99,1]\n  8057 ms  &lt;= \"&lt;instance: javax.crypto.SecretKey, $className: com.android.org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En examinant les appelants de ce constructeur, on s&rsquo;int\u00e9resse \u00e0 la classe <code>koe<\/code> de l&rsquo;application, en particulier \u00e0 sa m\u00e9thode <code>d<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>@Override \/\/ defpackage.kno\npublic final byte&#91;] d(String str, byte&#91;] bArr) {\n    qva.cg();\n    return SecretKeyFactory.getInstance(\"PBKDF2WithHmacSHA1\").generateSecret(new PBEKeySpec(str.toCharArray(), bArr, 10000, 256)).getEncoded();\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">La m\u00e9thode <code>koe.d<\/code> est appel\u00e9e par <code>hzk.a<\/code> et <code>jwn.a<\/code>. En pratique, dans notre cas elle est toujours appel\u00e9e par <code>jwn.a<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hookons les fonctions <code>koe.d<\/code> avec frida :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>&#91;Pixel 7a::com.google.android.apps.nbu.files ]-&gt; koe.d, args:\n\tpin: 2718\n\tarray:\nbc cf f7 58 33 d0 d4 49 62 8b b4 f2 d8 10 f8 d5 b0 9c 8d 29 4e 45 98 00 e2 f3 6a 8f 84 f7 15 01 \nbd 03 ac 96 01 0f cf d4 3f 67 f8 ae af cb 50 35 59 e5 ed 1c 5b d2 e2 93 a7 0b a4 9d 05 cc d4 9a \n25 85 19 06 b7 82 e0 f4 18 d4 04 89 63 23 38 0f 7c ba d2 a6 44 9a e0 69 18 81 c5 14 68 07 a4 bb \n5d 68 e2 5a d6 f2 f9 79 72 4b 92 9a 19 b0 a4 47 77 d2 61 ec c9 66 a9 56 bf ff db b6 aa 1d 60 2d \ne0 2c 56 47 cc e6 b0 80 4d 07 ba 11 b4 eb 4c 18 ac 21 a3 8c 94 da a7 54 72 bc 9b b1 b6 a2 62 9e \ne2 d3 b7 ca e7 25 db 99 e8 56 78 a8 9d 6a 5f 17 84 4d c6 86 d8 24 e0 9c 65 22 b8 60 49 ea 04 68 \n59 ca 0e c0 51 c4 83 9e 00 6e 12 95 56 29 c8 77 38 92 3a 7a d5 d2 05 86 ca 38 30 0b 75 c9 30 0e \n87 46 08 c4 38 ca bc 06 59 9c f2 b3 3b ca f8 33 f6 77 f7 cc aa 25 f4 5b 4c 07 61 27 b1 19 63 01 \n\nkoe.d, result:\n85 cc bc e2 a4 96 eb 7c 1e c6 35 3b 18 c5 63 8e 22 ef f8 4f 67 03 f3 1c 0d f7 63 1e 6d b6 23 f3<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Le premier argument de <code>koe.d<\/code> est le code PIN, le deuxi\u00e8me argument est un sel de 256 octets.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En retrouve ce sel dans le fichier <code>SafeFolderAuthStore.pb<\/code> stock\u00e9 dans <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>\/data\/data\/com.google.android.apps.nbu.files\/files\/<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>lynx:\/data\/data\/com.google.android.apps.nbu.files\/files # xxd SafeFolderAuthStore.pb\n00000000: 0aa5 0212 8002 bccf f758 33d0 d449 628b  .........X3..Ib.\n00000010: b4f2 d810 f8d5 b09c 8d29 4e45 9800 e2f3  .........)NE....\n00000020: 6a8f 84f7 1501 bd03 ac96 010f cfd4 3f67  j.............?g\n00000030: f8ae afcb 5035 59e5 ed1c 5bd2 e293 a70b  ....P5Y...&#91;.....\n00000040: a49d 05cc d49a 2585 1906 b782 e0f4 18d4  ......%.........\n00000050: 0489 6323 380f 7cba d2a6 449a e069 1881  ..c#8.|...D..i..\n00000060: c514 6807 a4bb 5d68 e25a d6f2 f979 724b  ..h...]h.Z...yrK\n00000070: 929a 19b0 a447 77d2 61ec c966 a956 bfff  .....Gw.a..f.V..\n00000080: dbb6 aa1d 602d e02c 5647 cce6 b080 4d07  ....`-.,VG....M.\n00000090: ba11 b4eb 4c18 ac21 a38c 94da a754 72bc  ....L..!.....Tr.\n000000a0: 9bb1 b6a2 629e e2d3 b7ca e725 db99 e856  ....b......%...V\n000000b0: 78a8 9d6a 5f17 844d c686 d824 e09c 6522  x..j_..M...$..e\"\n000000c0: b860 49ea 0468 59ca 0ec0 51c4 839e 006e  .`I..hY...Q....n\n000000d0: 1295 5629 c877 3892 3a7a d5d2 0586 ca38  ..V).w8.:z.....8\n000000e0: 300b 75c9 300e 8746 08c4 38ca bc06 599c  0.u.0..F..8...Y.\n000000f0: f2b3 3bca f833 f677 f7cc aa25 f45b 4c07  ..;..3.w...%.&#91;L.\n00000100: 6127 b119 6301 1a20 85cc bce2 a496 eb7c  a'..c.. .......|\n00000110: 1ec6 353b 18c5 638e 22ef f84f 6703 f31c  ..5;..c.\"..Og...\n00000120: 0df7 631e 6db6 23f3 220b 0880 9094 d706  ..c.m.#.\".......\n00000130: 1080 9c9c 3928 01                        ....9(.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Quant \u00e0 la valeur de retour de <code>koe.d<\/code>, c&rsquo;est un tableau de 32 octets :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>koe.d, result:\n85 cc bc e2 a4 96 eb 7c 1e c6 35 3b 18 c5 63 8e 22 ef f8 4f 67 03 f3 1c 0d f7 63 1e 6d b6 23 f3<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Cette valeur appara\u00eet aussi \u00e0 la fin de <code>SafeFolderAuthStore.pb<\/code> !<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dans la m\u00e9thode <code>jwn.a<\/code>, ce tableau (<code>d<\/code> dans le code d\u00e9compil\u00e9 par jadx) est compar\u00e9 avec un autre (stock\u00e9 dans la variable <code>a<\/code>) :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dans <code>jwn.a<\/code>, la valeur retourn\u00e9e par <code>koe.d<\/code> (<code>lcgVar.b.d((String) this.b, vipVar2.y())<\/code> ici) est compar\u00e9e avec une valeur de r\u00e9f\u00e9rence :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>byte&#91;] d = lcgVar.b.d((String) this.b, vipVar2.y());\nif (a.length == d.length) {\n    int i13 = 0;\n    char c4 = 0;\n    while (i13 &lt; a.length) {\n        ?? r10 = c4 | ((a&#91;i13] ^ d&#91;i13]) == true ? 1 : 0);\n        i13++;\n        c4 = r10;\n    }\n    if (c4 == 0) {\n        z2 = true;\n        plzVar.c(a6, new pfb(\"FilesSafeFolder_verifySecret\"));<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En conclusion, le d\u00e9verrouillage du dossier s\u00e9curis\u00e9 demande \u00e0 l&rsquo;utilisateur d&rsquo;entrer un code PIN. Ce code PIN est utilis\u00e9 avec un sel de 256 octets stock\u00e9 dans le fichier <code>SafeFolderAuthStore.pb<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">pour d\u00e9river une cl\u00e9 de 32 octets. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cette valeur est compar\u00e9e \u00e0 la valeur de r\u00e9f\u00e9rence, pr\u00e9sente elle aussi dans <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">le fichier <code>SafeFolderAuthStore.pb<\/code>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aucune op\u00e9ration de d\u00e9chiffrement des fichiers stock\u00e9s dans le dossier s\u00e9curis\u00e9 n&rsquo;est effectu\u00e9e.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Notons enfin que le nom des classes et m\u00e9thodes varient d&rsquo;une version \u00e0 l&rsquo;autre de Files by Google : Dans une version ant\u00e9rieure (la derni\u00e8re version test\u00e9e \u00e9tant la 2061783), la classe <code>koe<\/code> \u00e9tait nomm\u00e9e <code>kmv<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Un m\u00e9canisme d&rsquo;obfuscation semble donc \u00eatre mis en oeuvre lors de la compilation de l&rsquo;apk.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Le dossier s\u00e9curis\u00e9 est une fonctionnalit\u00e9 pr\u00e9sente sur les t\u00e9l\u00e9phones Android permettant de dissimuler des fichiers dans un emplacement dont l&rsquo;acc\u00e8s est prot\u00e9g\u00e9 par un code PIN ou un sch\u00e9ma. O\u00f9 les fichiers du dossier s\u00e9curis\u00e9 sont-ils stock\u00e9s ? La premi\u00e8re \u00e9tape est de d\u00e9terminer la localisation physique du dossier s\u00e9curis\u00e9. \u00c9num\u00e9rons les fichiers de [&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-451","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts\/451","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=451"}],"version-history":[{"count":2,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts\/451\/revisions"}],"predecessor-version":[{"id":454,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts\/451\/revisions\/454"}],"wp:attachment":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/media?parent=451"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/categories?post=451"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/tags?post=451"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}