<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>The Cave</title><link href="https://blog.xilokar.info/" rel="alternate"></link><link href="https://blog.xilokar.info/feeds/all.atom.xml" rel="self"></link><id>https://blog.xilokar.info/</id><updated>2025-06-17T00:00:00+02:00</updated><subtitle>Stuff that does not matter</subtitle><entry><title>SSTIC 2025 Demos</title><link href="https://blog.xilokar.info/sstic-2025-demos.html" rel="alternate"></link><published>2025-06-17T00:00:00+02:00</published><updated>2025-06-17T00:00:00+02:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2025-06-17:/sstic-2025-demos.html</id><summary type="html">A quick post to share the demo of my sstic 2025 talk</summary><content type="html">
      This is just small post to share the videos of my SSTIC talk.
      &lt;div id="demo1"&gt;&lt;/div&gt;

      &lt;script src="https://asciinema.org/a/gDz4LMlP6MaqShGjbgkhdcEYw.js" id="asciicast-gDz4LMlP6MaqShGjbgkhdcEYw" async="true"&gt;&lt;/script&gt;
      &lt;div id="demo2"&gt;&lt;/div&gt;
      &lt;script src="https://asciinema.org/a/jcagNNbivHmT89ZTGkfUfJxDl.js" id="asciicast-jcagNNbivHmT89ZTGkfUfJxDl" async="true"&gt;&lt;/script&gt;
      
    </content><category term="Misc"></category></entry><entry><title>Stm32wb55 FUS 2.0</title><link href="https://blog.xilokar.info/stm32wb55-fus-20.html" rel="alternate"></link><published>2025-06-07T00:00:00+02:00</published><updated>2025-06-07T00:00:00+02:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2025-06-07:/stm32wb55-fus-20.html</id><summary type="html">&lt;p&gt;A few days before my SSTIC presentation &lt;a class="reference external" href="https://www.sstic.org/2025/presentation/recupration_de_la_cle_des_firmwares_radio_du_stm32wb55/"&gt;Récupération de la clé des firmwares radio du stm32wb55&lt;/a&gt; (in french), while doing my slides, I was made aware of a new release of the &lt;cite&gt;FUS&lt;/cite&gt; for the &lt;cite&gt;stm32wb55&lt;/cite&gt;. And of course, the &lt;a class="reference external" href="/extracting-stm32wb55-cpu2-firmware-key.html"&gt;attack&lt;/a&gt; I was going to present 5 days later was no longer working...&lt;/p&gt;
</summary><content type="html">&lt;p&gt;A few days before my SSTIC presentation &lt;a class="reference external" href="https://www.sstic.org/2025/presentation/recupration_de_la_cle_des_firmwares_radio_du_stm32wb55/"&gt;Récupération de la clé des firmwares radio du stm32wb55&lt;/a&gt; (in french), while doing my slides, I was made aware of a new release of the &lt;cite&gt;FUS&lt;/cite&gt; for the &lt;cite&gt;stm32wb55&lt;/cite&gt;. And of course, the &lt;a class="reference external" href="/extracting-stm32wb55-cpu2-firmware-key.html"&gt;attack&lt;/a&gt; I was going to present 5 days later was no longer working...&lt;/p&gt;

&lt;p&gt;No release for 4 years, and a month before my talk, a new release with fixes ?&lt;/p&gt;
&lt;img alt="" src="/medias/hasard.gif" style="width: 100%;" /&gt;
&lt;p&gt;So I was good for a speedrun analysis of &lt;cite&gt;FUS&lt;/cite&gt; 2.0.&lt;/p&gt;
&lt;div class="section" id="what-was-fixed"&gt;
&lt;h2&gt;What was fixed&lt;/h2&gt;
&lt;div class="section" id="race-condition-in-flash-erase-page"&gt;
&lt;h3&gt;Race condition in flash_erase_page&lt;/h3&gt;
&lt;p&gt;The code that was handling flash page erasure was changed from something like&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;flash_erase_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C2CR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C2CR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xfffff807&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C2CR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;to something like that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;flash_erase_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C2CR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C2CR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xfffff807&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10002&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Preventing indeed a race condition that was allowing us to change the page &lt;cite&gt;FUS&lt;/cite&gt; was wanting to erase.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="ensuring-obl-launch"&gt;
&lt;h3&gt;Ensuring OBL_LAUNCH&lt;/h3&gt;
&lt;p&gt;In &lt;cite&gt;FUS 1.2.0&lt;/cite&gt;, the code to launch an &lt;cite&gt;OBL_LAUNCH&lt;/cite&gt; was like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;launch_obl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;dword&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wait_flash_done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xf00000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* Trigger OBL_LAUNCH */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;write_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x8000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, if &lt;cite&gt;OBL_LAUNCH&lt;/cite&gt; was forbidden by &lt;cite&gt;OPTLOCK&lt;/cite&gt;, the reset would not occure and the &lt;cite&gt;FUS&lt;/cite&gt; state machine was running the next step.&lt;/p&gt;
&lt;p&gt;In &lt;cite&gt;FUS 2.0&lt;/cite&gt; the code is more like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;launch_obl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;dword&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wait_flash_done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xf00000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* Trigger OBL_LAUNCH */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;write_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x8000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* Trigger ARM reset */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;SCB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AIRCR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x05fa0004&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Thus, enforcing a reset, and so preventing the state machine to run the next step unprotected (more details on attack in the &lt;a class="reference external" href="/extracting-stm32wb55-cpu2-firmware-key.html"&gt;original blog post&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="changing-the-fus-state-machine"&gt;
&lt;h3&gt;Changing the &lt;cite&gt;FUS&lt;/cite&gt; state machine&lt;/h3&gt;
&lt;p&gt;The &lt;cite&gt;FUS 1.2.0&lt;/cite&gt; state machine for firmware installation was this one:&lt;/p&gt;
&lt;img alt="" src="/medias/fus_update_state_machine.png" style="width: 100%;" /&gt;
&lt;p&gt;My original attack was at step &lt;cite&gt;3&lt;/cite&gt;, preventing the flash protection to be effective and then messing with the flash during step &lt;cite&gt;4&lt;/cite&gt; to gain code executin on &lt;cite&gt;CPU2&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;But there was another attack that could maybe have been done. During step &lt;cite&gt;2&lt;/cite&gt;, the &lt;cite&gt;CPU2&lt;/cite&gt; was calculating the hash of the ecnrypted firmware to feed it to the &lt;cite&gt;PKA&lt;/cite&gt;. This hash is slow to compute (especially if you slowdown &lt;cite&gt;CPU2&lt;/cite&gt;). So it would have been possible to change the encrypted binary (tricky, changing the start is easy but since the last page of the firmware has a hash of the unencrypted firmware, you must manage to at least write the last page of the firmware).&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;ST&lt;/cite&gt; probably spotted this potential issue and then choose to change the &lt;cite&gt;FUS 2.0&lt;/cite&gt; state machine to:&lt;/p&gt;
&lt;img alt="" src="/medias/fus2_state_machine_01.png" style="width: 100%;" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="closing-the-window"&gt;
&lt;h2&gt;Closing the window...&lt;/h2&gt;
&lt;p&gt;So, with this new state machine, The first step is to protect the flash by changing &lt;cite&gt;SFSA&lt;/cite&gt; and performing an &lt;cite&gt;OBL_LAUCNH&lt;/cite&gt; (with the protections mentionned above).&lt;/p&gt;
&lt;p&gt;So, as the flash was protected from &lt;cite&gt;CPU1&lt;/cite&gt; during both validation ans decryption of the image, we were no longer capable of altering the flash.&lt;/p&gt;
&lt;p&gt;I was starting to think that my talk was going to end by &amp;quot;But this no longer works&amp;quot;.&lt;/p&gt;
&lt;p&gt;Wait&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="and-opening-the-door"&gt;
&lt;h2&gt;...and opening the door&lt;/h2&gt;
&lt;p&gt;When &lt;cite&gt;FUS 2.0&lt;/cite&gt; has to protect the flash, it must know what size to protect right ? Ha yes, the header in the wireless image has a &lt;cite&gt;Flash (nb of 4K sectors)&lt;/cite&gt; byte. And this header is validated by the firmware signature.&lt;/p&gt;
&lt;p&gt;The code handling this is somehow like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;protect_flash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start_page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;start_page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xf4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="cm"&gt;/* write SFSA */&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;FLASH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SFR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FLASH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SFR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffff00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start_page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;obl_laucnh&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Appreciate the &lt;cite&gt;&amp;amp; 0xff&lt;/cite&gt;... so by feeding 0xf5 in the header, the CPU2 would only protect the upper page of the flash...&lt;/p&gt;
&lt;p&gt;Yes, but the header is validated by the signature.&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;Omg, the signature is only checked after the flash is protected !!!&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;pre class="literal-block"&gt;
 ____                          _   _
|  _ \__      ___ __   ___  __| | | |
| |_) \ \ /\ / / '_ \ / _ \/ _` | | |
|  __/ \ V  V /| | | |  __/ (_| | |_|
|_|     \_/\_/ |_| |_|\___|\__,_| (_)
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="tldr"&gt;
&lt;h2&gt;TLDR&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Write 0xf5 in the wireless image page info&lt;/li&gt;
&lt;li&gt;Start the installation (&lt;cite&gt;FUS&lt;/cite&gt; perform a reboot)&lt;/li&gt;
&lt;li&gt;Notice that &lt;cite&gt;SFSA&lt;/cite&gt; is at 0xff&lt;/li&gt;
&lt;li&gt;Patch &lt;cite&gt;FUS&lt;/cite&gt; to no longer check signature&lt;/li&gt;
&lt;li&gt;Enjoy&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This is how, with a 3 night work, instead of finishing my talk with shame, I got applaused ;)&lt;/p&gt;
&lt;/div&gt;
</content><category term="Misc"></category></entry><entry><title>ECC collision HOWTO</title><link href="https://blog.xilokar.info/ecc-collision-howto.html" rel="alternate"></link><published>2024-10-29T00:00:00+01:00</published><updated>2024-10-29T00:00:00+01:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2024-10-29:/ecc-collision-howto.html</id><summary type="html">&lt;p&gt;This is a small blog post I would have been happy to read while searching how to find ecc collision when dealing with how to exploit a limited write to flash.&lt;/p&gt;
&lt;p&gt;No rocket science, just a little write-up.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;This is a small blog post I would have been happy to read while searching how to find ecc collision when dealing with how to exploit a limited write to flash.&lt;/p&gt;
&lt;p&gt;No rocket science, just a little write-up.&lt;/p&gt;

&lt;div class="section" id="short-context"&gt;
&lt;h2&gt;Short Context&lt;/h2&gt;
&lt;p&gt;While working on a target, I found a primitive that allowed me to overwrite a flash page. By overwriting I mean, writing again. If you are not familiar with how some flash works, they must first be erased (aka, every bit is set to 1 (or 0) level, and the written (a bit can be flipped to the other state). Overwriting is doing the same flip again, but you can only flip on bit in the erased state to the written state.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ERASE
flash state:
0xffffffff

WRITE 0xffffff01

flash state:
0xffffff01

WRITE 0xffffff00

flash state:
0xffffff00

WRITE 0xffffff01

flash state:
0xffffff00
&lt;/pre&gt;
&lt;p&gt;See ? On the last write, the last bit was not set back to 1, but kept to 0.&lt;/p&gt;
&lt;p&gt;So, this set up with a limit on what we can overwrite to the flash page (eg, if this is the first page to be executed, a jump to another place), but this is something that can dealt with easily.&lt;/p&gt;
&lt;p&gt;Let's imagine that we have the &lt;tt class="docutils literal"&gt;jmp 0x00abcd&lt;/tt&gt; encoded as &lt;tt class="docutils literal"&gt;0x8000abcd&lt;/tt&gt; and that &lt;tt class="docutils literal"&gt;0x00000000&lt;/tt&gt; is a &lt;tt class="docutils literal"&gt;nop&lt;/tt&gt;&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Inital flash state:
0x8000abcd 0xffffffff 0xffffffff ... 0xffffffff
[jmp 0xabcd]

WRITE 0x00000000 0x80e00000 0xffffffff

flash state:
0x00000000 0x80e00000 0xffffffff ... 0xffffffff
[nop, jmp 0xe00000]
&lt;/pre&gt;
&lt;p&gt;and now we can jump to our (controlled) code&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="here-enter-ecc"&gt;
&lt;h2&gt;Here enter ECC&lt;/h2&gt;
&lt;p&gt;Unfortunatelly, the flash I was dealing with had a protection mechanism to deal with errors. Internally, every 256 bit pages of data was stored on 256+22 bits, and those 22 bits kept an ecc code to detect (and correct) errors.&lt;/p&gt;
&lt;p&gt;(ECC stands for Error Code Correction)&lt;/p&gt;
&lt;p&gt;A quick overview of what the problem is, with samller bits numbers:&lt;/p&gt;
&lt;p&gt;Wen doing a normal write of data&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ERASE
flash state:
DATA: 0xffffffff ECC: 0xff

WRITE 0xFFFFFF01 (calculated ecc=0x20)

flash state:
DATA: 0xffffff01 ECC: 0x20
&lt;/pre&gt;
&lt;p&gt;An ecc code is calulated and written&lt;/p&gt;
&lt;p&gt;For another data, the ecc is different:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ERASE
DATA: 0xffffffff ECC: 0xff

WRITE 0xffffff00 (calculated ecc=0x30)

flash state:
DATA: 0xffffff00 ECC: 0x30
&lt;/pre&gt;
&lt;p&gt;This mess with with our overwriting scheme (since ecc bits are stored in the flash, they also cannot be switched back to erase state)&lt;/p&gt;
&lt;p&gt;eg:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ERASE
flash state:
DATA: 0xffffffff ECC: 0xff

WRITE 0xFFFFFF01 (calculated ecc=0x20)

flash state:
DATA: 0xffffff01 ECC: 0x20

WRITE 0xFFFFFF00 (calculated ecc=0x30)

flash state:
DATA: 0xffffff00 ECC: 0x20 = (0x30 &amp;amp; 0x20)
&lt;/pre&gt;
&lt;p&gt;And here, the flash controller will detect that &lt;tt class="docutils literal"&gt;0xffffff00&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;0x20&lt;/tt&gt; don't match.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-necessary-maths-or-not"&gt;
&lt;h2&gt;The necessary maths (or not)&lt;/h2&gt;
&lt;p&gt;Disclaimer, I am not (I mean, no longer) a math guy, so I'll just put here the basics things needed to understand.&lt;/p&gt;
&lt;p&gt;The Ecc code generated is an hamming code. It has surely a lot of property, but what will interest us in the cas of ecc colisions, is that:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Is is generated by a simple multiplication by a generation matrice&lt;/li&gt;
&lt;li&gt;at the bit level, the sum is a xor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(for more maths, go to wikipedia)&lt;/p&gt;
&lt;p&gt;so:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Ecc(DATAS_BITS) = DATA_BITS x GEN_MATRICE
&lt;/pre&gt;
&lt;p&gt;and:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Ecc(DATA1 ^ DATA2) = Ecc(DATA1) ^ Ecc(DATA2)
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="calculating-ecc"&gt;
&lt;h2&gt;Calculating ECC&lt;/h2&gt;
&lt;p&gt;Back to our problem. We have:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Inital flash state:
0x8000abcd 0xffffffff 0xffffffff ... 0xffffffff ECC(inital_data)
[jmp 0xabcd]
&lt;/pre&gt;
&lt;p&gt;We want:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
flash state:
0x00000000 0x80e00000 0xffffffff ... 0xffffffff ECC(new_data)
&lt;/pre&gt;
&lt;p&gt;With&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;ECC(new_data) &amp;amp; ECC(initial_data) == ECC(new_data)&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;(ie, no bit writtent to zero in &lt;tt class="docutils literal"&gt;initial_ecc&lt;/tt&gt; must be switched back to 1 in &lt;tt class="docutils literal"&gt;new_ecc&lt;/tt&gt;)&lt;/p&gt;
&lt;p&gt;But we may also be happy with&lt;/p&gt;
&lt;pre class="literal-block"&gt;
flash state:
0x00000000 0x80e00000 0xefffffff ... 0xffffffff ECC(new_data_2)
&lt;/pre&gt;
&lt;p&gt;With the same constraint:&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;ECC(new_data_2) &amp;amp; ECC(initial_data) == ECC(new_data_2)&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;The first 64 bits of our payload need to be fixed, but we don't care of the state of the (256 - 64) bits remaining. So we have some latitude to forge a payload that will satisfy the constraint.&lt;/p&gt;
&lt;p&gt;Remember that &lt;tt class="docutils literal"&gt;Ecc&lt;/tt&gt; are additive ?&lt;/p&gt;
&lt;p&gt;Let's call &lt;tt class="docutils literal"&gt;bit_array_n&lt;/tt&gt; the 256 bits set to 0 except for bit n set to 1.&lt;/p&gt;
&lt;p&gt;So here, as we have&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;new_data_2 = new_data ^ bit_array_65&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;we have&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;ECC(new_data_2) == ECC(new_data) ^ ECC(bit_array_65)&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Let's call &lt;tt class="docutils literal"&gt;ECC_n = ECC(bit_array_n&lt;/tt&gt; ( the &lt;tt class="docutils literal"&gt;ECC&lt;/tt&gt; value of 256 bits set to 0 and bit n set to 1). (We can use an unprotected dev board of the same chip to extract thoses).&lt;/p&gt;
&lt;p&gt;And for any interesting test_data, we have &lt;tt class="docutils literal"&gt;N&lt;/tt&gt; bits (&lt;tt class="docutils literal"&gt;i1&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;i2&lt;/tt&gt;, ..., &lt;tt class="docutils literal"&gt;iN&lt;/tt&gt;) such as&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;test_data = new_data ^ (bit_array_i1 ^&amp;nbsp; ... ^ bit_array_iN)&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;ECC(test_data) = ECC(new_data) ^ ECC_i1 ^&amp;nbsp; ... ^ ECC_iN&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="finding-the-collision"&gt;
&lt;h2&gt;Finding the collision&lt;/h2&gt;
&lt;p&gt;Now we can easily compute the ECC of any payload we will try to overwrite. But we still needs to find a collision, ie, we need to find the set of bits from 65 to 256 to set to zero in order for the resulting ECC to be &lt;tt class="docutils literal"&gt;initial_ecc&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;So we must find (&lt;tt class="docutils literal"&gt;i1&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;i2&lt;/tt&gt;, ..., &lt;tt class="docutils literal"&gt;iN&lt;/tt&gt;) within &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;{65..256}&lt;/span&gt;&lt;/tt&gt; such that&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;ECC_i1 ^&amp;nbsp; ... ^ ECC_iN = ECC(new_data) ^ ECC(initial_data)&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;In order to do so, we first build for each couple and triplet of bits:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ECC(i,j)   = ECC(i) ^ ECC(j)
ECC(i,j,k) = ECC(i) ^ ECC(j) ^ ECC(k)
&lt;/pre&gt;
&lt;p&gt;And sort them by the number of bits set, and keep the ones with only 3,4 bits set.&lt;/p&gt;
&lt;p&gt;We have something like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ECC(069,146)      002100a0 (04 bits changed)
ECC(065,066)      00012880 (04 bits changed)
ECC(130,134)      00012804 (04 bits changed)
ECC(236,132)      00004281 (04 bits changed)
ECC(227,108)      00004805 (04 bits changed)
...
ECC(128,145,153)  00000284 (03 bits changed)
ECC(231,124,144)  00000282 (03 bits changed)
ECC(224,078,155)  00000281 (03 bits changed)
...
&lt;/pre&gt;
&lt;p&gt;At that point, I stopped doing automated thing and started to search by hand which bit set would produce the desired &lt;tt class="docutils literal"&gt;ECC(new_data) ^ ECC(initial_data)&lt;/tt&gt;, noticing that some combo leads to a one bit setter (eg &lt;tt class="docutils literal"&gt;ECC(224,078,155) ^ ECC(236,132) = 0x4000&lt;/tt&gt;)&lt;/p&gt;
&lt;p&gt;I was lucky in that &lt;tt class="docutils literal"&gt;ECC(new_data) ^ ECC(initial_data)&lt;/tt&gt; had only a few bit set. But hasn'it be the case, I would first search the &lt;tt class="docutils literal"&gt;ECC_i&lt;/tt&gt; space that would have minised the number of bits set.&lt;/p&gt;
&lt;p&gt;I also didn't handle the case where a bit is part of two set you want to use.&lt;/p&gt;
&lt;p&gt;For the record, here is the sequence I identified:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
target ecc 22e773
set_1:
00220202 -&amp;gt;  e571
set 2
00000502 -&amp;gt;  e073
set 3
00009011 -&amp;gt;  7062
set 4
00007000 -&amp;gt;    62
set 5 &amp;amp; 6
00020240
00020220 -&amp;gt;     2
set 7 &amp;amp; 8
00340002
00340000 -&amp;gt;     0
&lt;/pre&gt;
&lt;p&gt;And voilà !&lt;/p&gt;
&lt;p&gt;I can now overwrite the flash page with a controlled jump without the flash complaining about &lt;tt class="docutils literal"&gt;Ecc&lt;/tt&gt; errors.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I tried to make this as much simple as I could, but reading it back, not sure I managed to do so.&lt;/p&gt;
&lt;p&gt;Also note that, in my case, the &lt;tt class="docutils literal"&gt;ECC&lt;/tt&gt; was also calculated on the address of the flash page, but in the end, it does not change the approach used.&lt;/p&gt;
&lt;p&gt;Feel free to share if you found this interesting.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Misc"></category></entry><entry><title>Bypassing a noexec by elf roping</title><link href="https://blog.xilokar.info/bypassing-a-noexec-by-elf-roping.html" rel="alternate"></link><published>2023-11-27T00:00:00+01:00</published><updated>2023-11-27T00:00:00+01:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2023-11-27:/bypassing-a-noexec-by-elf-roping.html</id><summary type="html">&lt;p&gt;In this post, I will show you how I bypassed a noexec permission in a limited chrooted env.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In this post, I will show you how I bypassed a noexec permission in a limited chrooted env.&lt;/p&gt;

&lt;div class="section" id="short-context"&gt;
&lt;h2&gt;Short Context&lt;/h2&gt;
&lt;p&gt;Ok, so you have found this vuln in this software. You're happy. You can upload file, and you have the opportunity to execve a provided string. All seems done and you can enjoy a well deserved beer.&lt;/p&gt;
&lt;p&gt;But no.&lt;/p&gt;
&lt;p&gt;The service you hacked is well limited in facts. The upload directory is a tmpfs with noexec mount option. And the service runs in a chrooted env with no shell (sorry, no &lt;cite&gt;/bin/sh -c /tmp/upload/myscript.sh&lt;/cite&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="disclaimer"&gt;
&lt;h2&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;I don't pretend this a new approach or something never seen before. Just something I wasn't aware of ;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="initial-attempts"&gt;
&lt;h2&gt;Initial attempts&lt;/h2&gt;
&lt;p&gt;Luckily for us, even if the chroot is hardened, the provided application are dynamic executables, so we have access to &lt;cite&gt;ld.so&lt;/cite&gt; and &lt;cite&gt;libc.so&lt;/cite&gt;. In facts, in this system, it is the same &lt;cite&gt;musl&lt;/cite&gt; binary.&lt;/p&gt;
&lt;p&gt;My first attempt was to upload an elf in the tmpfs, and try an &lt;cite&gt;/lib/ld.so /tmp/uploaded.bin&lt;/cite&gt; in order to bypass the missing &lt;cite&gt;-x&lt;/cite&gt; permission on the file.&lt;/p&gt;
&lt;p&gt;While I later learnt it used to be a classical noexec bypass, kernels nowdays refuse to mmap part of a file on a nonexec fs with the &lt;cite&gt;PROT_EXEC&lt;/cite&gt; flag set, so no luck here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="first-victory"&gt;
&lt;h2&gt;First Victory&lt;/h2&gt;
&lt;p&gt;While playing with &lt;cite&gt;ld.so&lt;/cite&gt;, I noticed something that proved very interesting, memory locations of &lt;cite&gt;ld.so&lt;/cite&gt; and the &lt;cite&gt;uploaded.bin&lt;/cite&gt; elf file, while randomized due to &lt;cite&gt;ASLR&lt;/cite&gt;, were fixed relative to each other. This is not the case when executing an elf the normal way.&lt;/p&gt;
&lt;p&gt;Another thing to notice, is even if my elf binary is non-executable (and hence non executed), it still can be loaded. You just have to have no &lt;cite&gt;PROT_EXEC&lt;/cite&gt; segment in it and &lt;cite&gt;ld.so&lt;/cite&gt; and the kernel will happily map it.&lt;/p&gt;
&lt;p&gt;Once loaded, the last thing &lt;cite&gt;ld.so&lt;/cite&gt; will normally do, is to branch to your &lt;cite&gt;entry&lt;/cite&gt; point. Obviously, since we have  changed the segments to be non executable, it will fail miserabily.&lt;/p&gt;
&lt;p&gt;When exploiting, and you encounter a non-executable writeable address space is to go roping.&lt;/p&gt;
&lt;p&gt;Remember that our loaded elf and &lt;cite&gt;libc.so&lt;/cite&gt; are at a static offset ? So with a little math, we can tell &lt;cite&gt;ld.so&lt;/cite&gt; that our &lt;cite&gt;entry&lt;/cite&gt; point is far away from our loaded segments,  but rather in the &lt;cite&gt;libc.so&lt;/cite&gt; &lt;cite&gt;.text&lt;/cite&gt; section ;)&lt;/p&gt;
&lt;p&gt;And it works !&lt;/p&gt;
&lt;p&gt;We just need now to carefully choose where we are going to jump.&lt;/p&gt;
&lt;p&gt;But if we are going to rop, we need to be able to build a full ropchain on our stack, and unfortunately, the stack when entering the entry point is not really adapted... We just have a pointer to the argv and env strings in the stack.&lt;/p&gt;
&lt;p&gt;Our best chance would be to be able with one gadget to swap the stack to a memory controlled region.
But this turns out to be difficult (at least with the &lt;cite&gt;libc.so&lt;/cite&gt; I was targeting) without a little more help.&lt;/p&gt;
&lt;p&gt;A very well suitable function to switch stack is the &lt;cite&gt;longjmp&lt;/cite&gt; which restore an executable context.&lt;/p&gt;
&lt;p&gt;There are already calls in the &lt;cite&gt;ld.so&lt;/cite&gt; that makes use of it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;FUN_00148920&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Error recording dependencies for %s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lVar9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DAT_001919e8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="cm"&gt;/* WARNING: Subroutine does not return */&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;longjmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DAT_001919e0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What is interesting is that the pointer to the structure used for the &lt;cite&gt;longjmp&lt;/cite&gt; call is a writeable global.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="abusing-relocation"&gt;
&lt;h2&gt;Abusing Relocation&lt;/h2&gt;
&lt;p&gt;(hum, I may have spoiled a little here ... )&lt;/p&gt;
&lt;p&gt;What's fun with elf loading is relocations. It basicly tells the loader, &amp;quot;Hey, I will need to use this function, please write me its position here, so  that I can use it&amp;quot;. (There are Far better tutorials on relocation on the internet...).&lt;/p&gt;
&lt;p&gt;In fact you can even add an addendum to the position of the symbol you want the loader to inform you about.&lt;/p&gt;
&lt;p&gt;Remember how we tell the loader to set our entry point to where we want inside the &lt;cite&gt;libc.so&lt;/cite&gt; ? Well, we can use the same trick to let the loader know that we want &lt;cite&gt;address of symbol_a + addendum&lt;/cite&gt; written inside the &lt;cite&gt;libc.so&lt;/cite&gt; writeable &lt;cite&gt;.data&lt;/cite&gt; section. For exemple at the position of the pointer used during the &lt;cite&gt;longjmp&lt;/cite&gt; call.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
fffffffffe7fd9e0  001800000101 R_AARCH64_ABS64   000000000000000 puts
&lt;/pre&gt;
&lt;p&gt;And what's even more beautiful, is that we can use the loader to have the relocation point to our own object:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;init_stack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rop_exec_stack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rop_stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rop_chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GADGET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START_STACK_GADGET&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;address_of_rtld_fail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rop_exec_stack&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After patching the elf:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
fffffffffe7fd9e0  001800000101 R_AARCH64_ABS64  0000000000186140 \
                                                rop_exec_stack + 0
&lt;/pre&gt;
&lt;p&gt;Now, we juste have to point &lt;cite&gt;entry&lt;/cite&gt; to the call to &lt;cite&gt;longjmp&lt;/cite&gt;, and our first and only gadget will have everything done for us... We have set the stack pointer to our rop-chain that we can carefully write now...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="wrapping-it-all-together"&gt;
&lt;h2&gt;Wrapping it all together&lt;/h2&gt;
&lt;p&gt;I must admit this  was not the funniest part, finding suitables gadgets is very time consuming (especially on &lt;cite&gt;AARCH64&lt;/cite&gt; I found).&lt;/p&gt;
&lt;p&gt;We can still use the loader to have it calculate values and offsets for us&lt;/p&gt;
&lt;p&gt;But after some amount of time, I was able to write a rop chain that &lt;cite&gt;malloc&lt;/cite&gt; a huge buffer, &lt;cite&gt;mprotect&lt;/cite&gt; it to have it executable, &lt;cite&gt;memcpy&lt;/cite&gt; a payload (embedded in the &lt;cite&gt;uploade.bin&lt;/cite&gt; file) and then jump in it.&lt;/p&gt;
&lt;p&gt;And it is easy (as in, easy once done) to embedded a static elf in our payload and have it executed.&lt;/p&gt;
&lt;img alt="" src="/medias/pwned-strace.png" style="width: 100%;" /&gt;
&lt;p&gt;Now, you can work on escaping the chroot, but that is another story...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="final-thoughts"&gt;
&lt;h2&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;This was fun (and hard) to work on this.
I wrote this one shot, after final succes, so typos / error may be present (don't hesitate to contact me !)&lt;/p&gt;
&lt;p&gt;Feel free to share this blog post (and others ;) ) if you found it interesting.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Misc"></category><category term="Reverse"></category></entry><entry><title>Extracting stm32wb55 CPU2 firmware key</title><link href="https://blog.xilokar.info/extracting-stm32wb55-cpu2-firmware-key.html" rel="alternate"></link><published>2022-07-21T00:00:00+02:00</published><updated>2022-07-21T00:00:00+02:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2022-07-21:/extracting-stm32wb55-cpu2-firmware-key.html</id><summary type="html">&lt;p&gt;The &lt;cite&gt;stm32wb55&lt;/cite&gt; mcu is a dual core (&lt;cite&gt;cortex-m4&lt;/cite&gt;/&lt;cite&gt;cortex-m0&lt;/cite&gt;) mcu with integrated wireless capabilities (ble/thread/zigbee).&lt;/p&gt;
</summary><content type="html">&lt;p&gt;The &lt;cite&gt;stm32wb55&lt;/cite&gt; mcu is a dual core (&lt;cite&gt;cortex-m4&lt;/cite&gt;/&lt;cite&gt;cortex-m0&lt;/cite&gt;) mcu with integrated wireless capabilities (ble/thread/zigbee).&lt;/p&gt;

&lt;p&gt;The first core (the &lt;cite&gt;m4&lt;/cite&gt;, later referred as &lt;cite&gt;CPU1&lt;/cite&gt;) is for the customer. The second core (&lt;cite&gt;m0&lt;/cite&gt; known as &lt;cite&gt;CPU2&lt;/cite&gt; is dedicated to the low level wireless handling. The customer does not have access to this second core, neither to the firmwares running on it. Plus there is a bunch of security features embedded in the mcu to prevent access.&lt;/p&gt;
&lt;div class="section" id="why-does-this-suck"&gt;
&lt;h2&gt;Why does this suck ?&lt;/h2&gt;
&lt;p&gt;I could understand the company did not want to provide the customers direct access to the wireless core (I assume that the low level stacks are &lt;em&gt;valuable assets&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;But&lt;/p&gt;
&lt;p&gt;If you choose to go this way, at least don't mess up with the customer code.&lt;/p&gt;
&lt;p&gt;It appears that various operation involving the &lt;cite&gt;CPU2&lt;/cite&gt; (the wireless dedicated core) are not tolerant to interruption (power outage, cpu1 reset, more...) and, as stated in some documentation of the mcu, may lead to a bricked device, or to the need of a manual factory reset (which means a full erase of the cpu1 customer code, which is equivalent to a bricked device)&lt;/p&gt;
&lt;p&gt;This clearly sucks and I don't like it, so I decided to give it a look, to see what I could find.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="a-short-presentation"&gt;
&lt;h2&gt;A short presentation&lt;/h2&gt;
&lt;p&gt;The mcu comes with an embedded sram and flash. Both are shared between &lt;cite&gt;CPU1&lt;/cite&gt; and &lt;cite&gt;CPU2&lt;/cite&gt;, but parts of the sram and the flash are dedicated to &lt;cite&gt;CPU2&lt;/cite&gt;. There is an integrated features that prevent all access to customizable regions of the flash/sram except for &lt;cite&gt;CPU2&lt;/cite&gt;. Neither &lt;cite&gt;CPU1&lt;/cite&gt;, &lt;cite&gt;dma&lt;/cite&gt; or anything else can access it.&lt;/p&gt;
&lt;p&gt;We will focus on the flash, which is splitted by pages of 4k.&lt;/p&gt;
&lt;p&gt;The region dedicated to the cpu2 is selected by setting the first page to be locked. All other upper pages are locked.&lt;/p&gt;
&lt;p&gt;Setting this first locked page is done by writting in the so-called option-bytes registers (&lt;cite&gt;SFSA&lt;/cite&gt; for the secure flash start address) which is a small dedicated flash. Of course, write access to this part of the options bytes is allowed only to &lt;cite&gt;CPU2&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Another &lt;cite&gt;CPU2&lt;/cite&gt; related option bytes is the boot address of the cpu (&lt;cite&gt;SBRV&lt;/cite&gt;). Once again, write access is restricted.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
page 0x00 +-------------+ &amp;lt;- 0x0800000 start of flash
          | customer    |
          |   code      |
          |             |
          ~ ~ ~ ~ ~ ~ ~ ~

          ~ ~ ~ ~ ~ ~ ~ ~
          |             |
          |             |
          +-------------+ &amp;lt;- SFSA
          |             |
          |             |
          | CPU2-only   | &amp;lt;- SBRV
          |             |
page 0xff +-------------+ &amp;lt;- 0x080fffff end of flash

             Overview
&lt;/pre&gt;
&lt;p&gt;And obviously, dbg access to the &lt;cite&gt;CPU2&lt;/cite&gt; can also be forbidden.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="introducing-fus"&gt;
&lt;h2&gt;Introducing FUS&lt;/h2&gt;
&lt;p&gt;&lt;cite&gt;FUS&lt;/cite&gt; stands for Firmware Update Services. Basically, it allows to switch between different wireless stacks, handling all of the secure processing.&lt;/p&gt;
&lt;p&gt;The mcu is sold to the customer with &lt;cite&gt;FUS&lt;/cite&gt; already installed at the end of the flash.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
page 0x00 +-------------+ &amp;lt;- 0x0800000 start of flash
          | customer    |
          |   code      |
          |             |
          ~ ~ ~ ~ ~ ~ ~ ~

          ~ ~ ~ ~ ~ ~ ~ ~
          |             |
          |             |
          |             |
page 0xf4 +-------------+ &amp;lt;- SFSA / SBRV
          |             |
          |     FUS     |
          |             |
page 0xff +-------------+ &amp;lt;- 0x080fffff end of flash

             FUS only
&lt;/pre&gt;
&lt;p&gt;The last pages of the flash are marked as secure, and the boot vector of the &lt;cite&gt;CPU2&lt;/cite&gt; is set to the start of &lt;cite&gt;FUS&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;With a shared mem and an hardware inter-processor communication mechanism (out of scope), the customer application code can order &lt;cite&gt;FUS&lt;/cite&gt; to perform some tasks.&lt;/p&gt;
&lt;p&gt;For example, it can request to install a wireless firmware. To do so, the ST-provided image must be written in the internal flash, and an &lt;cite&gt;FUS_FW_UPGRADE&lt;/cite&gt; command must be sent to &lt;cite&gt;FUS&lt;/cite&gt;.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
page 0x00 +-------------+ &amp;lt;- 0x0800000 start of flash
          | customer    |
          |   code      |
          |             |
          ~ ~ ~ ~ ~ ~ ~ ~

          ~ ~ ~ ~ ~ ~ ~ ~
          |             |
page 0xdc +-------------+
          |             |
          |  encrypted  |
          |   wireless  |
          |   firmware  |
          |             |
page 0xf4 +-------------+ &amp;lt;- SFSA / SBRV
          |             |
          |     FUS     |
          |             |
page 0xff +-------------+ &amp;lt;- 0x080fffff end of flash

           Before install
&lt;/pre&gt;
&lt;p&gt;As stated in the documentation (AN5185 on ST site), there will be some expected reboots during the install procedure. This is due to the fact that option bytes modifications are only applied after a reset. In fact there is even a special bit (&lt;cite&gt;OBL_LAUNCH&lt;/cite&gt;) in a register in the flash controller that performs this reset.&lt;/p&gt;
&lt;p&gt;Let's monitor &lt;cite&gt;SFSA&lt;/cite&gt;/&lt;cite&gt;SBRV&lt;/cite&gt; during this install process.&lt;/p&gt;
&lt;p&gt;After first reset&lt;/p&gt;
&lt;pre class="literal-block"&gt;
page 0x00 +-------------+ &amp;lt;- 0x0800000 start of flash
          | customer    |
          |   code      |
          |             |
          ~ ~ ~ ~ ~ ~ ~ ~

          ~ ~ ~ ~ ~ ~ ~ ~
          |             |
page 0xdc +-------------+ &amp;lt;- SFSA
          |             |
          |  encrypted  |
          |   wireless  |
          |   firmware  |
          |             |
page 0xf4 +-------------+ &amp;lt;- SBRV
          |             |
          |     FUS     |
          |             |
page 0xff +-------------+ &amp;lt;- 0x080fffff end of flash

           First reset
&lt;/pre&gt;
&lt;p&gt;The firmware and &lt;cite&gt;FUS&lt;/cite&gt; pages are secure, but the &lt;cite&gt;CPU2&lt;/cite&gt; still boots on &lt;cite&gt;FUS&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Then there is another reboot and we have:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
page 0x00 +-------------+ &amp;lt;- 0x0800000 start of flash
          | customer    |
          |   code      |
          |             |
          ~ ~ ~ ~ ~ ~ ~ ~

          ~ ~ ~ ~ ~ ~ ~ ~
          |             |
page 0xdc +-------------+ &amp;lt;- SFSA / SBRV
          |             |
          |             |
          |   wireless  |
          |   firmware  |
          |             |
page 0xf4 +-------------+
          |             |
          |     FUS     |
          |             |
page 0xff +-------------+ &amp;lt;- 0x080fffff end of flash

           After install
&lt;/pre&gt;
&lt;p&gt;At this point the wireless firwmare is runing. We can still however ask it to switch back to &lt;cite&gt;FUS&lt;/cite&gt;.
We then have again&lt;/p&gt;
&lt;pre class="literal-block"&gt;
page 0x00 +-------------+ &amp;lt;- 0x0800000 start of flash
          | customer    |
          |   code      |
          |             |
          ~ ~ ~ ~ ~ ~ ~ ~

          ~ ~ ~ ~ ~ ~ ~ ~
          |             |
page 0xdc +-------------+ &amp;lt;- SFSA
          |             |
          |  encrypted  |
          |   wireless  |
          |   firmware  |
          |             |
page 0xf4 +-------------+ &amp;lt;- SBRV
          |             |
          |     FUS     |
          |             |
page 0xff +-------------+ &amp;lt;- 0x080fffff end of flash

           FUS activated
&lt;/pre&gt;
&lt;p&gt;We can ask to delete the current wireless firmware with &lt;cite&gt;FUS_FW_DELETE&lt;/cite&gt;, and after another reset:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
page 0x00 +-------------+ &amp;lt;- 0x0800000 start of flash
          | customer    |
          |   code      |
          |             |
          ~ ~ ~ ~ ~ ~ ~ ~

          ~ ~ ~ ~ ~ ~ ~ ~
          |             |
page 0xdc +-------------+
          |             |
          |    Empty    |
          |    Pages    |
          |             |
          |             |
page 0xf4 +-------------+ &amp;lt;- SBRV / SFSA
          |             |
          |     FUS     |
          |             |
page 0xff +-------------+ &amp;lt;- 0x080fffff end of flash

           FUS running
&lt;/pre&gt;
&lt;p&gt;(of course, the unciphered wireless image is erased...)&lt;/p&gt;
&lt;p&gt;A similar procedure can be used to upgrade &lt;cite&gt;FUS&lt;/cite&gt; itself, involving more reset (probably due to a phase of relocation of the new &lt;cite&gt;FUS&lt;/cite&gt; on top of the old &lt;cite&gt;FUS&lt;/cite&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="firmware-image"&gt;
&lt;h2&gt;Firmware image ...&lt;/h2&gt;
&lt;p&gt;Let's look at the provided wireless firmware / FUS upgrade images provided by ST. They are (sort of) documented in the ST application note. Obviously, they are signed by ST, and encrypted, so not much to do as of now. Still, dig inside the github &lt;a class="reference external" href="https://github.com/STMicroelectronics/STM32CubeWB"&gt;repository&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="hidden-in-plain-sight"&gt;
&lt;h2&gt;... hidden in plain sight&lt;/h2&gt;
&lt;p&gt;More precisely, look at the history of the firmware &lt;a class="reference external" href="https://github.com/STMicroelectronics/STM32CubeWB/tree/master/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x"&gt;binaries&lt;/a&gt;. We can see updates andnew wireless protocols released. But there is more... during release &lt;cite&gt;v1.5.0&lt;/cite&gt;, a file with a different pattern name appears: &lt;cite&gt;stm32wb5x_FUS_fw_1_0_2.bin&lt;/cite&gt;...&lt;/p&gt;
&lt;p&gt;And yes...&lt;/p&gt;
&lt;p&gt;above all odds,&lt;/p&gt;
&lt;p&gt;it's the unciphered binary !!!&lt;/p&gt;
&lt;p&gt;Well, at least, we have something to work on. Even if it is not the latest &lt;cite&gt;FUS&lt;/cite&gt; version, we may learn some valuable info.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="wireless-install-steps"&gt;
&lt;h2&gt;Wireless install steps&lt;/h2&gt;
&lt;p&gt;After a bit of reversing of the &lt;cite&gt;FUS&lt;/cite&gt; image, the wireless image install process can be more detailled.&lt;/p&gt;
&lt;div class="section" id="step-1-image-authentication"&gt;
&lt;h3&gt;Step 1 Image authentication&lt;/h3&gt;
&lt;p&gt;When ordering to procede to a wireless image install, &lt;cite&gt;FUS&lt;/cite&gt; first search for 2 footers. The one with the ST signature, and the one with the image info.&lt;/p&gt;
&lt;p&gt;A sha256 of the image is then calculated and an edcsa verification is performed, using an embedded (but hidden) public key. This ecdsa verification uses the PKA (public key accelerator) hardware block.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pub_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;zero_mem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init_pka&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pka_ecdsa_verif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pub_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;stop_pka&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the image is authenticated, FUS saves it state in a dedicated page at the end of the secured part of the flash, set the &lt;cite&gt;SFSA&lt;/cite&gt; register to the beginning of the image and trigger an OBL reset.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="step-2-deciphering-the-image"&gt;
&lt;h3&gt;Step 2 Deciphering the image&lt;/h3&gt;
&lt;p&gt;&lt;cite&gt;FUS&lt;/cite&gt; restart and knows it must now decipher the image. This is done in place by using AES in CTR mode with a nonce provided in the image footer, a start number of 2 (because why not) and a key stored in the end of the secured part of the flash. Each page is deciphered in a temporary memory buffer, erased, and the rewritten with the cleartext.&lt;/p&gt;
&lt;p&gt;Once done, the next step is to save the state in the internal flash, set &lt;cite&gt;SBRV&lt;/cite&gt; to the entry point of the wireless image and trigger an OBL reset.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="the-pka"&gt;
&lt;h2&gt;The PKA&lt;/h2&gt;
&lt;p&gt;This hardware block accelerate calculation for various public key algorithms. It has a dedicated ram used to store various parameters (with hardcoded offset for each mode of calculation). Once setup and started, the block is busy during a while until the result beeing available (again, at an hardcoded offset of the &lt;cite&gt;PKA ram&lt;/cite&gt;).&lt;/p&gt;
&lt;p&gt;So, why don't we try to monitor the PKA registers during step 1 of the install process ?&lt;/p&gt;
&lt;p&gt;So, I wrote a small loop on my demoboard that would monitor &lt;cite&gt;PKA&lt;/cite&gt; status register, and indeed, I saw the &lt;cite&gt;FUS&lt;/cite&gt; using the block.&lt;/p&gt;
&lt;p&gt;Next steps is to see if we can override the &lt;cite&gt;PKA&lt;/cite&gt; result, and thus bypass signature verification.&lt;/p&gt;
&lt;p&gt;First, slightly modify the image so that the signature does not match, but still the image is valid, by modifying the build version in the image footer. Indeed, an attempt to install this binary fails with an &lt;cite&gt;FUS_STATE_IMG_NOT_AUTHENTIC&lt;/cite&gt; error.&lt;/p&gt;
&lt;p&gt;Then retry the install whilemonitoring the PKA End of Operation flag, and then quickly write &lt;cite&gt;0&lt;/cite&gt; at the right place in the &lt;cite&gt;PKA ram&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;And install continues !&lt;/p&gt;
&lt;p&gt;Good, we can bypass signature verification.&lt;/p&gt;
&lt;p&gt;I was about to focus on how to exploit this signature bypass, but unfortunately, later on, while poking with the demoboard, I accidentally bricked it (don't remember exactly how).&lt;/p&gt;
&lt;p&gt;So I try to reproduce the signature bypass with a custom board, but it constantly failed...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="hardened-fus-1"&gt;
&lt;h2&gt;Hardened FUS - 1&lt;/h2&gt;
&lt;p&gt;In facts, the demoboard was programmed with the &lt;cite&gt;v1.1.1&lt;/cite&gt; of &lt;cite&gt;FUS&lt;/cite&gt;, but the purchased &lt;cite&gt;stm32wb55&lt;/cite&gt; were programmed with &lt;cite&gt;v1.2.0&lt;/cite&gt;. There must have been some changes in this area.&lt;/p&gt;
&lt;p&gt;I retry my monitoring of the &lt;cite&gt;PKA&lt;/cite&gt; status register and found that it seems not to be used. Reading the reference manual, I spotted a feature I was not aware of. Access to the &lt;cite&gt;PKA&lt;/cite&gt; block can dynamically be restricted to &lt;cite&gt;CPU2&lt;/cite&gt; by writting in the &lt;cite&gt;SYSCFG_SIPCR&lt;/cite&gt;. And indeed, &lt;cite&gt;FUS v1.2.0&lt;/cite&gt; seems to use this feature. So goodbye signature bypass on this version...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="you-shall-not-erase"&gt;
&lt;h2&gt;You shall not erase !&lt;/h2&gt;
&lt;p&gt;At that point, it was logic to try to recover the cleartext of this new version of &lt;cite&gt;FUS&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;I liked the approach of monitoring &lt;cite&gt;FUS&lt;/cite&gt; activity by watching the various block status/control registers, so I wrote a small monitor of the flash activity of &lt;cite&gt;FUS&lt;/cite&gt; during the deletion of firmware. And we can clearly see &lt;cite&gt;FUS&lt;/cite&gt; erasing pages one at a time before switching back &lt;cite&gt;SFSA&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;But look at the (old) code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;flash_erase_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;dword&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C2CR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="cm"&gt;/* write page to erase */&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;write_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C2CR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xfffff805&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="cm"&gt;/* re read */&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C2CR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="cm"&gt;/* start erase */&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;write_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C2CR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;cr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See how the register is re-read ?&lt;/p&gt;
&lt;p&gt;So, I wrote a little code that monitor &lt;cite&gt;Flash.C2CR&lt;/cite&gt;, wait for the desired page to be scheduled for an erase and overwrite the value with a different page. And it worked ! Not a 100% success, but still enough to grab each erased page one by one.&lt;/p&gt;
&lt;p&gt;Applied this technic during a &lt;cite&gt;FUS&lt;/cite&gt; self-update from &lt;cite&gt;v1.2.0&lt;/cite&gt; to &lt;cite&gt;v1.2.0&lt;/cite&gt; and I managed to get the code for this latest version of &lt;cite&gt;FUS&lt;/cite&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="hardened-fus-2"&gt;
&lt;h2&gt;Hardened FUS - 2&lt;/h2&gt;
&lt;p&gt;First, I wanted to go back to the &lt;cite&gt;PKA&lt;/cite&gt; call just to confirm what I suspected.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pub_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;undefined4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local_18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x37921932&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;memset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init_pka&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* lock pka access */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SYSCFG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIPCR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;write_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SYSCFG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIPCR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;probably_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pka_ecdsa_verif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pub_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;deinit_pka&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cm"&gt;/* unlock pka access */&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SYSCFG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIPCR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;write_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SYSCFG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIPCR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xfffffffb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Yes, it is now locking PKA access from &lt;cite&gt;CPU1&lt;/cite&gt; during signature check.
Also, quite funny:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_sfsa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;st_pub_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x29912337&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="cm"&gt;/* signature ok */&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;write_flash_sfsa&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next_sfsa&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;verify_signature is now returning a weird &lt;cite&gt;0x29912337&lt;/cite&gt;.... Looks like someone attended an &amp;quot;How to protect your code from fault attacks&amp;quot; course...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="burn-after-reading"&gt;
&lt;h2&gt;Burn after reading&lt;/h2&gt;
&lt;p&gt;Remember that any changes to &lt;cite&gt;sfsa&lt;/cite&gt; requires a reset, triggered by a write to the &lt;cite&gt;OBL_LAUNCH&lt;/cite&gt; bit of the &lt;cite&gt;FLASH_CR&lt;/cite&gt; register of the flash controller ?&lt;/p&gt;
&lt;pre class="literal-block"&gt;
3.10.5 - Flash memory control register (FLASH_CR)

...

Bit 27 OBL_LAUNCH: Forces the option byte loading

When set to 1, this bit forces the option byte reloading.
This bit is cleared only when the option byte loading is complete.
It cannot be written if OPTLOCK is set.

0: Option byte loading complete
1: Option byte loading requested
&lt;/pre&gt;
&lt;p&gt;Yes, there is a mechanism to prevent unwanted write to the flash controller by first entering a sequence 2-words key sequence before beeing abale to perform some write and erase. And another sequence for option bytes.&lt;/p&gt;
&lt;p&gt;Turns out that you can also relock access by writing a &lt;cite&gt;1&lt;/cite&gt; to the &lt;cite&gt;LOCK&lt;/cite&gt; bit of the controller.&lt;/p&gt;
&lt;p&gt;With that in mind, I came with a strategy:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;let the &lt;cite&gt;PKA&lt;/cite&gt; verify signature&lt;/li&gt;
&lt;li&gt;monitor the &lt;cite&gt;SYSCFG.SIPCR&lt;/cite&gt; to know when it is has done so&lt;/li&gt;
&lt;li&gt;wait for the state and &lt;cite&gt;SFSA&lt;/cite&gt; to be writtent in flash/option bytes by monitoring flash activity&lt;/li&gt;
&lt;li&gt;lock &lt;cite&gt;OPTLOCK&lt;/cite&gt; to prevent OBL reset&lt;/li&gt;
&lt;li&gt;rewrite the signed firmware with my modified one&lt;/li&gt;
&lt;li&gt;unlock &lt;cite&gt;OPTLOCK&lt;/cite&gt; to reset and make &lt;cite&gt;FUS&lt;/cite&gt; continue&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I did not want to brick my board on the first try, I just made a first test without the flash rewriting step.&lt;/p&gt;
&lt;p&gt;Here I must first admit I had made a mistake when thinking at my strategy.
Instead of the real code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;launch_obl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;dword&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wait_flash_done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xf00000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;write_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x8000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I had this version in mind:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;launch_obl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;dword&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;wait_flash_done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xf00000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;read_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;write_volatile_4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x8000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I was thinking that, locking the &lt;cite&gt;OPTLOCK&lt;/cite&gt; would let the &lt;cite&gt;CPU2&lt;/cite&gt; in an endless loop, and after unlocking &lt;cite&gt;OPTLOCK&lt;/cite&gt; the board would reset and continue the install process.
So, I was expecting a reset and this situation:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
page 0x00 +-------------+ &amp;lt;- 0x0800000 start of flash
          | customer    |
          |   code      |
          |             |
          ~ ~ ~ ~ ~ ~ ~ ~

          ~ ~ ~ ~ ~ ~ ~ ~
          |             |
page 0xdc +-------------+ &amp;lt;- SFSA
          |             |
          |  encrypted  |
          |   wireless  |
          |   firmware  |
          |             |
page 0xf4 +-------------+ &amp;lt;- SBRV
          |             |
          |     FUS     |
          |             |
page 0xff +-------------+ &amp;lt;- 0x080fffff end of flash

           FUS activated
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="cpu2-code-execution"&gt;
&lt;h2&gt;CPU2 code execution&lt;/h2&gt;
&lt;p&gt;I did have a reset, but after it, I was in this sitation:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
page 0x00 +-------------+ &amp;lt;- 0x0800000 start of flash
          | customer    |
          |   code      |
          |             |
          ~ ~ ~ ~ ~ ~ ~ ~

          ~ ~ ~ ~ ~ ~ ~ ~
          |             |
page 0xdc +-------------+ &amp;lt;- SFSA / SBRV
          |             |
          |             |
          |   wireless  |
          |   firmware  |
          |             |
page 0xf4 +-------------+
          |             |
          |     FUS     |
          |             |
page 0xff +-------------+ &amp;lt;- 0x080fffff end of flash

           After install
&lt;/pre&gt;
&lt;p&gt;With a running wireless firmware.&lt;/p&gt;
&lt;p&gt;Indeed, this is coherent:
the &lt;cite&gt;FUS&lt;/cite&gt; had stored its state in flash, but was expecting a reset in order for &lt;cite&gt;SFSA&lt;/cite&gt; to be updated. Instead, it just returned from the &lt;cite&gt;launch_obl()&lt;/cite&gt; function and continue the next step in his state machine, until the next OBL reset (the one needed to change th &lt;cite&gt;SBRV&lt;/cite&gt;)&lt;/p&gt;
&lt;p&gt;But what is the next step after image signature verification ? Yes... unciphering.&lt;/p&gt;
&lt;p&gt;So instead of waiting for the reset after unlocking back the &lt;cite&gt;OPTLOCK&lt;/cite&gt;, I monitored the flash pages where the image was written, and bingo, I clearly saw pages beeing erased and rewrittent. I had access to the unciphered image...&lt;/p&gt;
&lt;p&gt;Good, but I had already access to the code...&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;Wait...&lt;/p&gt;
&lt;p&gt;I have read access to the unciphered image but I can also modify it !&lt;/p&gt;
&lt;p&gt;The path now was straightforward: change the first page with a reset vector pointing to an unsecure flash page while &lt;cite&gt;FUS&lt;/cite&gt; was unciphering the other pages and wait for the &lt;cite&gt;OBL&lt;/cite&gt; reset.&lt;/p&gt;
&lt;p&gt;Of course, after the reset the &lt;cite&gt;CPU2&lt;/cite&gt; was stuck, but after writing at the controlled page a jump back to the expected reset vector, the &lt;cite&gt;CPU2&lt;/cite&gt; was back online and functionnal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="key-extraction"&gt;
&lt;h2&gt;Key extraction&lt;/h2&gt;
&lt;p&gt;Then, instead of jumping back to the firmware, I wrote a small dumper code that will exfilter the upper pages of the secure zone of the flash to a &lt;cite&gt;CPU1&lt;/cite&gt; readable area.&lt;/p&gt;
&lt;p&gt;Within thoses pages, lies the AES key used by &lt;cite&gt;FUS&lt;/cite&gt; to uncipher the firmware images.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
 ____                          _   _
|  _ \__      ___ __   ___  __| | | |
| |_) \ \ /\ / / '_ \ / _ \/ _` | | |
|  __/ \ V  V /| | | |  __/ (_| | |_|
|_|     \_/\_/ |_| |_|\___|\__,_| (_)
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Security through obscurity is not security.&lt;/li&gt;
&lt;li&gt;&lt;cite&gt;FUS&lt;/cite&gt; also has a service to store customer AES keys inside the secure flash. My advice is not to use this to store valuable encryption keys, since they can now been extracted also.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you enjoyed this read, feel free to tweet about it, or to &lt;a class="reference external" href="https://blog.xilokar.info/pages/about-me.html"&gt;contact me&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Misc"></category></entry><entry><title>Firmware key extraction by gaining EL3</title><link href="https://blog.xilokar.info/firmware-key-extraction-by-gaining-el3.html" rel="alternate"></link><published>2022-06-07T00:00:00+02:00</published><updated>2022-06-07T00:00:00+02:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2022-06-07:/firmware-key-extraction-by-gaining-el3.html</id><summary type="html">&lt;img alt="" src="/medias/pwned.jpg" style="width: 100%;"/&gt;
&lt;div class="section" id="a-bit-of-history"&gt;
&lt;h2&gt;A bit of history&lt;/h2&gt;
&lt;p&gt;A few months back, I turned my attention on my fiber gateway. So I ordered the same model on ebay, unsoldered and dump the nand, and after &lt;em&gt;a lot&lt;/em&gt; of work, managed to have a clear view of the system, from bootloader to userland.&lt;/p&gt;
&lt;p&gt;Basically, the bootloader check the signature of the kernel image, uncrypt the kernel image with a bootloader stored key, which in turn, uncrypt the rootfs image and voila.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[YYYY] / # ls
README       dev          lib          opt          sbin         usr
bin          etc          media        proc         sys          var
config       exports      mnt          root         tftpboot
ctmp         home         nonexisting  run          tm
[YYYY] / # cat README
If you can read this, congratulations !

Feel free to drop me an email, xxxx@yyyy.zz
&lt;/pre&gt;
&lt;/div&gt;</summary><content type="html">&lt;img alt="" src="/medias/pwned.jpg" style="width: 100%;" /&gt;
&lt;div class="section" id="a-bit-of-history"&gt;
&lt;h2&gt;A bit of history&lt;/h2&gt;
&lt;p&gt;A few months back, I turned my attention on my fiber gateway. So I ordered the same model on ebay, unsoldered and dump the nand, and after &lt;em&gt;a lot&lt;/em&gt; of work, managed to have a clear view of the system, from bootloader to userland.&lt;/p&gt;
&lt;p&gt;Basically, the bootloader check the signature of the kernel image, uncrypt the kernel image with a bootloader stored key, which in turn, uncrypt the rootfs image and voila.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[YYYY] / # ls
README       dev          lib          opt          sbin         usr
bin          etc          media        proc         sys          var
config       exports      mnt          root         tftpboot
ctmp         home         nonexisting  run          tm
[YYYY] / # cat README
If you can read this, congratulations !

Feel free to drop me an email, xxxx&amp;#64;yyyy.zz
&lt;/pre&gt;

&lt;p&gt;I managed to flash a custom rootfs (since only the kernel was signature checked)&lt;/p&gt;
&lt;p&gt;So I contacted the vendor, and explained what I did.&lt;/p&gt;
&lt;p&gt;They fixed the issue by adding a signature check on the rootfs, and told me that, even if &amp;quot;impressed&amp;quot;, as this was an old model with no secure boot nor secure storage, it was &lt;em&gt;easy&lt;/em&gt; (as in &amp;quot;yes we know we can not secure this&amp;quot;).&lt;/p&gt;
&lt;p&gt;And they were right, nothing would have prevented me from flashing my own bootloader with my own public key or signature bypass.&lt;/p&gt;
&lt;p&gt;Still, I was happy.&lt;/p&gt;
&lt;p&gt;Then, a challenge came to my mind: &amp;quot;what if I could break into their latest model?&amp;quot;&lt;/p&gt;
&lt;p&gt;So back to ebay.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="first-glimpses"&gt;
&lt;h2&gt;First glimpses&lt;/h2&gt;
&lt;p&gt;I tried to apply the same methodology with more or less success&lt;/p&gt;
&lt;img alt="" src="/medias/emmc.jpeg" style="width: 100%;" /&gt;
&lt;p&gt;But still, with more ebay purchases, I managed to get a dump.&lt;/p&gt;
&lt;p&gt;Which was obviously encrypted. Even the bootloader... so, secure boot, as expected.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="serial-output"&gt;
&lt;h2&gt;Serial Output&lt;/h2&gt;
&lt;p&gt;Probing unpopulated connector footprints on the pcb during boot did not lead to anything. But I finally managed to find the serial signal on one resistor.&lt;/p&gt;
&lt;p&gt;Following the tracks, it leads to the usb-c power connector, through some small IC. Adding a pull-up to the SBU pin of the usb-c connector and we have the bootlogs directly on the usb-c connector:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
----
BTRM
V1.2
L1CD
MMUI
MMUA
DATA
ZBBS
MAIN
OTP?
REF?
REFP
RTF?
RTFP
OTPP
FSBT
EMMC
IMG?
IMGL
UHD?
UHDP
RLO?
RLOP
AHD?
ROT?
ROTA
MID?
MIDP
AHDP
SBI?
SBIA
PASS
HELO
5.0206-1.0.38-42.42
CPU0
L1CD
MMUI
MMUB
ZBBS
MAIN


xxx8a cfe decompressor (ROM).
DDR test done successfully
  - Decompressing ...
  - Decompression OK Load 1fc00000, Entry Point 1fc00000.

Base: 5.02_06
CFE version 1.0.38-163.180 for BCM963158 (64bit,SP,LE)
Build Date: Fri Dec  6 19:01:14 CET 2019 (xxxx&amp;#64;yyyy)
Copyright (C) 2000-2015 Broadcom Corporation.
XXX Version: 1.0


.text:   000000001fc00000-000000001fc2ea00
.rodata: 000000001fc2f000-000000001fd253f8
.data:   000000001fd26000-000000001fd26fc0
.bss:    000000001fd26fc0-000000001fd2c3f8
.stack:  000000001fd2e000-000000001fd6e000
.heap:   000000001fd6e000-000000001ff8e000

CPU Started with slow freq strap.
POR CPU frequency: 400 Mhz
CPU frequency set to 1675MHz
Boot Strap Register: 0x3fffff77
Chip ID: BCM63153_B1, Broadcom B53 Quad Core: 1675MHz
Total Memory: 536870912 bytes (512MB)
Enabling CCI500 coherency ... Done.
pmc_init:PMC using DQM mode
MMC: bus setup with width 8, sdr
SDHCI MMC init done.
i2c-gpio: using gpio24 (sda) gpio25 (scl).
i2c-gpio: using gpio15 (sda) gpio16 (scl).
fb0: SSD1320 frame buffer device (160x80 screen)

Serial: xxxx-xx-x-(xx)xx-xx-xxxxx / 0
Mac:    xx:xx:xx:xx:xx:xx
Bundle: xxxxxxxxxxxxxxxx

## Booting in standard mode.
 - Trying to load new bank0: no bank0 to flash, read fail
Loading firmware from 'emmc0:bank1': 31432192 bytes in 0.707 seconds.
ATF partition at offset 0000000011801000, size 11956
 - Validation stage 1.
 - Validation stage 2.
 - Kernel signature OK!
 - Decrypting kernel.
OP-TEE partition at offset 0000000011804000, size 129524
 - Validation stage 1.
 - Validation stage 2.
 - Kernel signature OK!
 - Decrypting kernel.
kernel partition at offset 0000000011824000, size 4574388
 - Validation stage 1.
 - Validation stage 2.
 - Kernel signature OK!
 - Decrypting kernel.
dtb partition at offset 0000000011c81000, size 21940
 - Validation stage 1.
 - Validation stage 2.
 - Kernel signature OK!
 - Decrypting kernel.
NOTICE:  BL31: v1.4(release):42d1e692
NOTICE:  BL31: Built : 18:19:32, Oct  2 2019
I/TC:
I/TC: OP-TEE version: 3.7.0-110-g6ba85038 (gcc version 8.3.0 )
                       #1 Tue Jan 28 13:57:39 UTC 2020 aarch64
I/TC: rng200_rng_init ...
I/TC: RNG200 init done.
I/TC: Initialized
ATF returned in EL2.
E/LD:  init_elf:259 sys_open_ta_bin(7011a688-ddde-4053-a5a9-
7b3c4ddf13b8)
E/TC:? 0 init_with_ldelf:229 ldelf failed with res: 0xffff000e
E/TC:? 0 tee_ta_open_session:727 Failed. Return error 0xffff000e
&lt;/pre&gt;
&lt;p&gt;Arm Trusted Firmware, Op-tee, all signed and encrypted...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="test-mode"&gt;
&lt;h2&gt;Test mode&lt;/h2&gt;
&lt;p&gt;During my work on the previous model, I found that by shorting two pins of one connector on the pcb, the board booted in a so-called test-mode. This mode, after a custom network authentication, allow to boot on a network loaded firmware image without signature check.&lt;/p&gt;
&lt;p&gt;So I needed to do two things:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Trigger the test mode on the new model&lt;/li&gt;
&lt;li&gt;Do the network authentication&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To ease the process, first, let's get root on the device (sorry, won't cover that part, I know it's an achievement in its own, but I am focused on breaking secure boot, and yes, it would be sufficient to display the &lt;cite&gt;Pwned&lt;/cite&gt; message on the screen of the device...but we are not here just for the lulz).&lt;/p&gt;
&lt;p&gt;We can find some interesting things in /sys/class&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[YYYY] / # ls /sys/class/xxxgpio/boot-eth
data_in    data_out   device     direction  pin_num    subsystem  uevent
&lt;/pre&gt;
&lt;p&gt;boot-eth ? Sounds good !&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[YYYY] / # while true; do
&amp;gt; cat /sys/class/xxxgpio/boot-eth/data_in
&amp;gt; sleep 0.1
&amp;gt; done
0
0
0
&lt;/pre&gt;
&lt;p&gt;And then start poking arround all test points until we can see a 1 showing up.&lt;/p&gt;
&lt;p&gt;I am focusing around the usb-c connector (just a feeling) and all the glue.&lt;/p&gt;
&lt;p&gt;And it's a match.&lt;/p&gt;
&lt;p&gt;Well, sort of. It seems that when injecting 3.3v on one test point, the gpio value alterns between 0 and 1. But injecting the 3.3v at the right time on boot get us a straight 1.&lt;/p&gt;
&lt;p&gt;I got the feeling that &amp;quot;boot-eth&amp;quot; can be triggered by an appropriate usb-pd command/response, the test point coming from a gpio output of the usb-pd chip&lt;/p&gt;
&lt;img alt="" src="/medias/6710.jpg" style="width: 100%;" /&gt;
&lt;p&gt;I decided to cope with that, and not searching more. Since I can easily trigger test mode with this cursed method.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="test-mode-authentication"&gt;
&lt;h2&gt;Test mode authentication&lt;/h2&gt;
&lt;p&gt;Here again, I got helped by my work on the previous model.
Basically, in test mode, the board send an udp packet with a once, that has to be hashed with a per device specific key and sent back. This way, the board ensure it is on a vendor's developper owned network.&lt;/p&gt;
&lt;p&gt;The key is derivated from a primary key. To sum up, each device owns a primary key, and can derivate key0, key1 roughly by calculating&lt;/p&gt;
&lt;pre class="literal-block"&gt;
rc4(md5(key_index + primary_key))
&lt;/pre&gt;
&lt;p&gt;Each key index serves a specific purpose, and for test mode we need key1&lt;/p&gt;
&lt;p&gt;On the previous model, primary_key was stored in the nand (aside with the mac address and other per-device stuff). But on this device, we do not have unciphered access to it.&lt;/p&gt;
&lt;p&gt;But as we are root, and the device needs to be able to get a key index for it's own purpose, unless all encryption is done in the secure world.&lt;/p&gt;
&lt;p&gt;But we are lucky:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[YYYY] /root # xxxkeys
usage: xxxkeys [OPTS] &amp;lt;key_idx&amp;gt; &amp;lt;key_len&amp;gt;
Where OPTS is one of:
   -b      base64 output
   -h      hexadecimal ouput (default)
   -n      fail when lock
[YYYY] /root # xxxkeys 1 16
ab553c48d5ade7426929c4c5b7f03aa
&lt;/pre&gt;
&lt;p&gt;With that key, we are able to authenticate our network for the device to boot in test mode.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="a-note-on-firmware-images"&gt;
&lt;h2&gt;A note on firmware images&lt;/h2&gt;
&lt;p&gt;The firmware image format is roughtly the same as the previous model, so I reused the scripts I wrote:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
xilokar&amp;#64;xilokar:~$ Tools/parse_tag.py -i image-xxxxx8r_bank1_4.2.9
crc:     ce46779a
magic:   3658382b
version: 00000002
len:     01e28000
tag version &amp;lt;xxxxx8r_bank1_4.2.9&amp;gt;
Build the 2021-02-08 18:38:30 by yyy&amp;#64;zzzzzzz
5 partitions present

partition 0
     crc:    0cf4403a
     offset: 00001000
     size:   00002eb4 (end=00003eb4)
     type:   00000002
     flags:  00000005
             skrypted
             xz
     name:   &amp;lt;part_00&amp;gt;
Computed crc: 0cf4403a

partition 1
     crc:    349f1619
     offset: 00004000
     size:   0001f9f4 (end=000239f4)
     type:   00000004
     flags:  00000005
             skrypted
             xz
     name:   &amp;lt;part_01&amp;gt;
Computed crc: 349f1619

partition 2
     crc:    64bde3c9
     offset: 00024000
     size:   0045cf94 (end=00480f94)
     type:   00000000
     flags:  00000005
             skrypted
             xz
     name:   &amp;lt;bcm63xx-kernel&amp;gt;
Computed crc: 64bde3c9

partition 3
     crc:    3bea7801
     offset: 00481000
     size:   000055b4 (end=004865b4)
     type:   00000003
     flags:  00000001
             skrypted
     name:   &amp;lt;bcm63xx-dtb&amp;gt;
Computed crc: 3bea7801

partition 4
     crc:    d7c8c9d2
     offset: 00487000
     size:   019a1000 (end=01e28000)
     type:   00000001
     flags:  00000001
             loaded in ram
     name:   &amp;lt;rootfs&amp;gt;
Computed crc: d7c8c9d2
Tag md5: cc6b4289d689c0b713e8afe7825022b8
&lt;/pre&gt;
&lt;p&gt;It consist of a bunch of binary encapsulated, each with a type and flags.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;xz means the partition is compressed&lt;/li&gt;
&lt;li&gt;skrypted means the partition is encrypted and signed&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="bootloader-dump"&gt;
&lt;h2&gt;Bootloader dump&lt;/h2&gt;
&lt;p&gt;Actually, I did that before venturing into test mode, but it does not matter.&lt;/p&gt;
&lt;p&gt;Reuse the same approach as for my attack on the &lt;a class="reference external" href="https://blog.xilokar.info/pwning-the-bcm61650.html"&gt;brcm61650&lt;/a&gt; with a kernel module dumping the right memory space ( we have &lt;cite&gt;.text&lt;/cite&gt;, &lt;cite&gt;.rodata&lt;/cite&gt; addresses in the bootlog)&lt;/p&gt;
&lt;p&gt;With the dump in hand, let's look at how the firmware is loaded.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;probably_load_partition&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partition_info&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;load_mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;suggested_load_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;param_5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uVar1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uVar2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;memmap_entry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pmVar3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;uchar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;local_18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local_10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;undefined8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;s_%s_partition_at_offset_, _size_%&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;load_mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LAB_1fc06ec4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%s_partition_must_be_skrypted&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;maybe_update_load_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xf4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;probably_load_partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;atf_part&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ATF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;LAB_10000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ATF_pointer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atf_part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;probably_load_partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;optee_part&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;OP-TEE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                 &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x10800000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;probably_load_partition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;kernel_part&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                  &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;kernel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                   &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x80000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;probably_load_partition&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;dtb_part&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dtb&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                     &lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x1fb70000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We see that even though, in test mode, kernel (and dtb) do not need to be skrypted, ATF and OP-TEE must be.&lt;/p&gt;
&lt;p&gt;Let's look at how an image is &amp;quot;unskrypted&amp;quot;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;unskrypt_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;in_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;out_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cipher_index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uVar2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;undefined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local_24bc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hash_sha256&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;undefined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;session_key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;rsa_key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;public_key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;undefined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;auStack9264&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;272&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;skrypt_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local_2320&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cbc_ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2162&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ltm_desc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PTR_s_LibTomMath_1fd1f800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x198&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;crypt_register_cipher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PTR_s_aes_1fd1f558&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;crypt_register_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PTR_s_sha256_1fd1f658&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;local_2320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x154&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;again_swap_bytes&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;local_2320&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;magic&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x534b5259&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bad_magic&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;again_swap_bytes&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;local_2320&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bad_version.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local_2320&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key_index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%i:_key_number_too_big&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;local_2320&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key_index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="cm"&gt;/* ...*/&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get_public_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_2320&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;public_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;unable_to_get_public_key_!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;support_decrypt_kernel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;-_Validation_stage_1?&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PTR_aes_key_0_0_1fd27028&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;local_2320&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key_index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PTR_aes_key_1_0_1fd27048&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;local_2320&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key_index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sooo, we might have a pointer to the aes key !&lt;/p&gt;
&lt;p&gt;Unfortunatley, there is this funtion:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;probably_clear_sensitive_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;longlong&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lVar1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pvVar2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;undefined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;ppuVar3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;undefined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;ppuVar4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;support_decrypt_kernel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;iVar5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;ppuVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PTR_aes_key_1_0_1fd27048&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;ppuVar4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PTR_aes_key_0_0_1fd27028&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;zeromem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ppuVar4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;maybe_dma_sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ppuVar4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;zeromem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ppuVar3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;maybe_dma_sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ppuVar3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;iVar5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iVar5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;ppuVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ppuVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;ppuVar4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ppuVar4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;lVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;probably_get_board_serial_info&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;zeromem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;pvVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;maybe_dma_sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x26&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pvVar2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;that is called just before passing the hand to &lt;cite&gt;ATF&lt;/cite&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;pvVar4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;probably_clear_sensitive_data&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;probably_run_atf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pvVar4&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="n"&gt;ulonglong&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cRead_8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ATF_returned_in_EL%d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cRead_8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Secure_OS_left_at_EL3!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, no chance to grab the aes key used to decrypt the firmware from the post-boot memory dump.&lt;/p&gt;
&lt;p&gt;By looking further (too much code to dump here, so no screenshot) we can see that the firmware aes key are loaded from an encrypted partition. The partition is encrypted with a per-device key, accessible only when in EL3.&lt;/p&gt;
&lt;p&gt;Good luck...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="back-to-test-mode"&gt;
&lt;h2&gt;Back to test mode&lt;/h2&gt;
&lt;p&gt;Let's look at what we can do in test mode.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;ATF&lt;/cite&gt; and &lt;cite&gt;OP-TEE&lt;/cite&gt; must be skrypted.&lt;/p&gt;
&lt;p&gt;So focus on kernel (or dtb).&lt;/p&gt;
&lt;p&gt;The &lt;cite&gt;xz&lt;/cite&gt; flags is quite interesting. If not set, the partition is copied to the default location. but the &lt;cite&gt;xz&lt;/cite&gt; flags loads an header with a target load destination.&lt;/p&gt;
&lt;p&gt;With that in mind, maybe we could try to over-load the &lt;cite&gt;ATF&lt;/cite&gt; (which is run at EL3) with our own code?&lt;/p&gt;
&lt;p&gt;Nice try, but each loaded partition fills an memory_map entry, and no overwrite is allowed.
(kudo to the developpers)&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[00010000-0001ffff pmc.boot]
[00080000-00d0a807 kernel]
[10000000-10007027 ATF]
[10800000-108543af OP-TEE]
[11800000-11db4fff imagetag]
[1fb80000-1fbfffff cfe.mmu]
[1fc00000-1fffffff cfe]
&lt;/pre&gt;
&lt;p&gt;I found a glitch in the loading code that would have allow to overwrite some code by wrapping the address, but found it unexploitable (data abort)&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Exception Class: Data Abort From Current EL
Fault address: &amp;lt;ffffffffffffffff&amp;gt;
Fault status: Translation fault, level 0
&lt;/pre&gt;
&lt;p&gt;At that point, I was about to give up.&lt;/p&gt;
&lt;p&gt;But...&lt;/p&gt;
&lt;p&gt;Remember, the &lt;cite&gt;ATF&lt;/cite&gt; partition muste be skrypted.
So it's signature is checked, and then it is decrypted.&lt;/p&gt;
&lt;p&gt;Let's look a bit further. Here is the format of the skrypted partition:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;magic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// &amp;quot;SKRY&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_offset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;key_index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;session_key_crypted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And at the code that handle deciphering:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Kernel_signature_OK&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;support_decrypt_kernel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xmemcmp&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skr_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;zero__1fd27068&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xmemcmp&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skr_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_key_crypted&lt;/span&gt;
&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;zero__1fd27068&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;kernel seems encrypted, which is unsupported&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xmemcmp&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skr_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;zero__1fd27068&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xmemcmp&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;skr_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_key_crypted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;zero__1fd27068&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot; - Decrypting_kernel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;cipher_index&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;crypt_find_cipher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s_aes_1fc2f862&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;cbc_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cipher_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;skr_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;session_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;cbc_ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cipher_index&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;unable_to_setup_aes_cbc&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;decrypt_aes_cbc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;cbc_ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;unable_to_decipher_kernel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;cipher_index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;out_len&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uVar3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uVar2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xffffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See ?
To decide if it will decrypt the partition with the session_key, the unskrypt function check if the &lt;cite&gt;iv&lt;/cite&gt; and the &lt;cite&gt;encrypted_session_key&lt;/cite&gt; are not full of zero.&lt;/p&gt;
&lt;p&gt;So, instead of the unskrypted &lt;cite&gt;ATF&lt;/cite&gt; binary, we can inject the ciphered &lt;cite&gt;ATF&lt;/cite&gt; binary. Of course, we can not modify this image. But fuck hell, maybe with luck, the ciphered binary are valid aarch64 instruction that could help us ?&lt;/p&gt;
&lt;p&gt;So let's grab all the signed &lt;cite&gt;ATF&lt;/cite&gt; partition we can find and objdump the ciphered payload.&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;yes !&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ./Tools/parse_skrypt.py ---dump atf.bin
magic:   534b5259
version: 00000003
offset:  00000154
len:     00002d60
key_id:  00000000
iv:  b'20c4f...a83c56c9492063d761bf17108d'
encrypted_session_key:  b'd1be...3aa0a87f1a1f'
Dumping to &amp;lt;atf.bin.ciphered&amp;gt;

$ objdump -D -b binary -m aarch64 atf.bin.ciphered
atf.bin.ciphered:     file format binary

Disassembly of section .data:

0000000000000000 &amp;lt;.data&amp;gt;:
0:       301752cf        adr     x15, 0x2ea59
4:       d07e50fe        adrp    x30, 0xfca1e000
8:       b530904a        cbnz    x10, 0x61210
&lt;/pre&gt;
&lt;p&gt;One of the ciphered &lt;cite&gt;ATF&lt;/cite&gt; partition decodes as three valid instructions, with the third one being a jump to an non-reserved memory_maped region (as the &lt;cite&gt;atf&lt;/cite&gt; is loaded at &lt;cite&gt;0x10000000&lt;/cite&gt; and the jump is relative, it gives us &lt;cite&gt;0x10061210&lt;/cite&gt;, between &lt;cite&gt;ATF&lt;/cite&gt; and &lt;cite&gt;OP-TEE&lt;/cite&gt;) ! (Luckily, &lt;cite&gt;x10&lt;/cite&gt; is not zero at that point of the code).&lt;/p&gt;
&lt;p&gt;And if we omit the &lt;cite&gt;xz&lt;/cite&gt; flag, the ciphered data will be copied as-is to the default &lt;cite&gt;ATF&lt;/cite&gt; memmap.&lt;/p&gt;
&lt;p&gt;So now, let's roll.&lt;/p&gt;
&lt;p&gt;build a &amp;quot;kernel&amp;quot; image that we &lt;cite&gt;xz&lt;/cite&gt; at the jump location, pack it with a skrypted &lt;cite&gt;ATF&lt;/cite&gt; image, with &lt;cite&gt;iv&lt;/cite&gt; and &lt;cite&gt;key&lt;/cite&gt; set to &lt;cite&gt;000...00&lt;/cite&gt;, and boom, we have code execution at &lt;cite&gt;EL3&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;We then just need to rejump to the code that handle partition decryption, and we can dump the shared firmware aes key...&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;bl_printf&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x1fc2d7f4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;hexdump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;bl_printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;DUMP_%s_: %16x: &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="n"&gt;bl_printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%02x &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;bl_printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;load_bootinfo&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x1fc0e768&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dump_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;load_bootinfo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;hexdump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;AES_0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x1fd2be70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;hexdump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;AES_1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x1fd2bdf0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;ENTRY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_Reset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;SECTIONS&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10061210&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;startup64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bss&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;bss&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;COMMON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ALIGN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;stack_top&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;pre class="literal-block"&gt;
DUMP_AES_0: 000000001fd2be70: a1 ... 33
DUMP_AES_1: 000000001fd2bdf0: d8 ... c4
&lt;/pre&gt;
&lt;p&gt;(obviously, I won't disclose)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="bypassing-rootfs-signature"&gt;
&lt;h2&gt;Bypassing rootfs signature&lt;/h2&gt;
&lt;p&gt;Just a quick note on that.&lt;/p&gt;
&lt;p&gt;To bypass the rootfs signature included in the new kernel released, just load a previous (signed)  kernel (that do not check rootfs signature, just decrypt it) and then load a specially crafted module that mimic kexec on the new (modified) kernel on the crafted rootfs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Custom firmware on a &amp;quot;secure boot&amp;quot; device.&lt;/p&gt;
&lt;p&gt;The bootloader in itself is also signed/ciphered with an OTP key that is set unreadable before the ROM execute the bootloader. An hardware fault injection attack would probably be necessary to bypass that, but that's beyond my capabilities (atm).&lt;/p&gt;
&lt;p&gt;The vendor has been contacted and fixed the bootloader.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Misc"></category><category term="Reverse"></category></entry><entry><title>Pwning the bcm61650</title><link href="https://blog.xilokar.info/pwning-the-bcm61650.html" rel="alternate"></link><published>2022-04-04T00:00:00+02:00</published><updated>2022-04-04T00:00:00+02:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2022-04-04:/pwning-the-bcm61650.html</id><summary type="html">&lt;p&gt;The percello prc6000, also known as bcm61650 after Broadcom bought the company, is a chip used in 3g femtocells (Home-nodeB).&lt;/p&gt;
&lt;img alt="" src="/medias/bootloader_serial.png" style="width: 100%;"/&gt;
&lt;p&gt;Here is a summary writeup of how I achieved to bypass its secure ROM to run arbitrary firmwares.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;The percello prc6000, also known as bcm61650 after Broadcom bought the company, is a chip used in 3g femtocells (Home-nodeB).&lt;/p&gt;
&lt;img alt="" src="/medias/bootloader_serial.png" style="width: 100%;" /&gt;
&lt;p&gt;Here is a summary writeup of how I achieved to bypass its secure ROM to run arbitrary firmwares.&lt;/p&gt;

&lt;div class="section" id="intro"&gt;
&lt;h2&gt;Intro&lt;/h2&gt;
&lt;p&gt;The bcm61650 is present in a femtocell of a large french operator. It allows you to have a small 3g tower in your house over your dsl/fiber line. It's an optional box you plug in your dsl box, with what looks like a pcie connector.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="from-pcie-in-box-to-standalone-ethernet"&gt;
&lt;h2&gt;From PCIe in box to standalone Ethernet&lt;/h2&gt;
&lt;p&gt;When pluged in, the board present itself as a pci ethernet chip, that performs a bootp and load its firmware over tftp and then connects to an hardcoded IP to establish an ipsec tunnel to the core network (I won't cover this part). In order to fully use the femtocell for playing with osmocom, I decided to try get rid of the hardcoded parts.&lt;/p&gt;
&lt;p&gt;To ease debugging, I decided to try to tweak it into a standalone, ethernet based, board, in order to be able to start, stop or reboot the board without having to mess with pci scanning and hotplug.&lt;/p&gt;
&lt;p&gt;Desoldering the link between the pci ethernet chip and the bcm61650&lt;/p&gt;
&lt;img alt="" src="/medias/standalone01.jpg" style="width: 100%;" /&gt;
&lt;p&gt;And with a few probes, managing to get the board powered and booting.&lt;/p&gt;
&lt;img alt="" src="/medias/standalone02.jpg" style="width: 100%;" /&gt;
&lt;p&gt;With uart output.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Node-H FM-loader v1.2
booting in ******* mode
changing CPU frequency... done
image verification success
copying initrd at 0X8F6C8000...
copying kernel...
bytes: 3338752
booting kernel...
&lt;/pre&gt;
&lt;p&gt;Hum... &lt;tt class="docutils literal"&gt;image verification&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="first-glimpses"&gt;
&lt;h2&gt;First glimpses&lt;/h2&gt;
&lt;p&gt;The firmware loaded over tftp is 11Mb.&lt;/p&gt;
&lt;p&gt;binwalk output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
DECIMAL       HEXADECIMAL     DESCRIPTION
---------------------------------------------------------------------
123953        0x1E431         Copyright string: &amp;quot;Copyright (c) MIPS
                              Technologies, Inc. All rights reserved.
125092        0x1E8A4         CRC32 polynomial table, little endian
126181        0x1ECE5         Copyright string: &amp;quot;Copyright (c) MIPS
                              Technologies, Inc. All rights reserved.
128416        0x1F5A0         SHA256 hash constants, little endian
131224        0x20098         uImage header, header size: 64 bytes,
                              header CRC: 0x8ACC835E, image name:
                              &amp;quot;Linux-2.6.31.12-Percello-1.12-9&amp;quot;
131288        0x200D8         gzip compressed data, has original file
                              name: &amp;quot;vmlinux.bin&amp;quot;
1740800       0x1A9000        Squashfs filesystem
&lt;/pre&gt;
&lt;p&gt;So, a bunch of unkown stuff at the start, then kernel and root filesystem.&lt;/p&gt;
&lt;p&gt;Trying a simple change in the kernel/rootfs:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Node-H FM-loader v1.2
booting in ******* mode
changing CPU frequency... done
image verification failed
failed to boot: halt
&lt;/pre&gt;
&lt;p&gt;Yeah, obviously&lt;/p&gt;
&lt;p&gt;Some string a the start of the binary blob:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Percello bootloader version 0.6 (from
Silicon type:
, silicon ver:
, feature ver:
, ROM ver:
Boot block
not found
FM signature has invalid length
&lt;/pre&gt;
&lt;p&gt;Did not see the &lt;tt class="docutils literal"&gt;Percello bootloader version 0.6&lt;/tt&gt; during boot. And the &lt;tt class="docutils literal"&gt;FM signature&lt;/tt&gt; suggests we surely have a chain of bootloaders until linux (which is expected).&lt;/p&gt;
&lt;p&gt;Trying to change a string in the bootloader completly blocks the boot, so bootloaders are either checksumed or a signature is checked.&lt;/p&gt;
&lt;p&gt;Where to go from now ?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="got-root"&gt;
&lt;h2&gt;Got root ?&lt;/h2&gt;
&lt;p&gt;Extract initrd with binwalk, check /etc/password&lt;/p&gt;
&lt;p&gt;Long story short: empty root password.&lt;/p&gt;
&lt;p&gt;side-note: from now on, I will always check for empty password &lt;em&gt;before&lt;/em&gt; trying to build an hashcat rule&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="got-dump"&gt;
&lt;h2&gt;Got Dump ?&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
dd if=/dev/mem  bs=4k | nc
&lt;/pre&gt;
&lt;p&gt;With luck, the memory used during boot time will not (yet) be overwritten by linux.&lt;/p&gt;
&lt;p&gt;Using the strings in the firmware and in the location of the matchings strings in the memory dump, we can find the location in ram of the bootloader, and thus adjust the load offset of the binary in our favorite RE tool.&lt;/p&gt;
&lt;p&gt;After a few hours of digging things out:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The percello bootloader is loaded at &lt;tt class="docutils literal"&gt;0x83fe0000&lt;/tt&gt;
It then loads the FM loader&lt;/li&gt;
&lt;li&gt;The FM loader is loaded at &lt;tt class="docutils literal"&gt;0x83f80000&lt;/tt&gt;
he is responsible for loading kernel and initrd&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both use code from ROM (&lt;tt class="docutils literal"&gt;0x9fc00xxx&lt;/tt&gt;), for signature verification.&lt;/p&gt;
&lt;p&gt;Time to go further down in our analysis.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="got-rom"&gt;
&lt;h2&gt;Got Rom ?&lt;/h2&gt;
&lt;p&gt;The dd approach to dump rom does not seems to work:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
# dd if=/dev/mem bs=1 skip=$((0x9fc00000)) count=10
dd: /dev/mem: Bad address
#
&lt;/pre&gt;
&lt;p&gt;Not a surprise, the rom is surely not mapped in linux. But hey, we are root, and we can load modules!&lt;/p&gt;
&lt;p&gt;So grab a linux-2.6.31.12 archive, try to build a close enough kernel (did I mentionned it was mips based ?) play with symbol versioning &lt;em&gt;and voila&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;linux/module.h&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;linux/kernel.h&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;linux/init.h&amp;gt;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dump_mem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Dumping: %08x&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;DUMP:%08x: %02x&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__init&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dump_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Dump init&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// dump rom ?&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;dump_mem&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x9fc00000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0x9fd00000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dump_exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;printk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Dump exit&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;module_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_init&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;module_exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dump_exit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;MODULE_AUTHOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Xilokar&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;MODULE_DESCRIPTION&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Dump driver&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;MODULE_LICENSE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;GPL&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;!--  --&gt;
&lt;p&gt;(do not pay attention to code)&lt;/p&gt;
&lt;p&gt;grab kernel messages from console, grep, sed, xxd and we have our ROM dump.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;more time digging things out&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="hello-rsa-my-old-friend"&gt;
&lt;h2&gt;Hello RSA my old friend&lt;/h2&gt;
&lt;p&gt;Remember the functions from ROM used in both percello bootloader and FM-loader ? Without surprise, they are also used in the ROM code, to check the percello bootloader signature.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;s_Secured_device_-_OTP2:_verificat_9fc0dda8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FUN_9fc0d15c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DAT_bf400888&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;DAT_bf400880&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;DAT_bf400ae8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;DAT_bf40088c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iVar1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;s_FAILED_9fc0e364&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;FUN_9fc0d15c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;undefined4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;undefined4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;param_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="n"&gt;undefined4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;param_3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;undefined4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;param_4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;undefined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;auStack152&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;undefined&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;auStack132&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;FUN_9fc0c380&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auStack132&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;FUN_9fc0c96c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auStack132&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;param_2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;FUN_9fc0d020&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auStack132&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;auStack152&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;FUN_9fc0ccc0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auStack152&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;param_3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;param_4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Probably, &lt;tt class="docutils literal"&gt;FUN_9fc0c380&lt;/tt&gt; is hash init, &lt;tt class="docutils literal"&gt;FUN_9fc0c96c&lt;/tt&gt; hash process and &lt;tt class="docutils literal"&gt;FUN_9fc0d020&lt;/tt&gt; hash finalize.
The hash size is 160,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;FUN_9fc0c380&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;undefined4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x67452301&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xefcdab89&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x98badcfe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10325476&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xc3d2e1f0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x19&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x17&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x18&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we have good old Sha constants, so hash is surely sha1&lt;/p&gt;
&lt;p&gt;The last function (&lt;tt class="docutils literal"&gt;FUN_9fc0ccc0&lt;/tt&gt;) builds a &lt;tt class="docutils literal"&gt;0x80&lt;/tt&gt; long structure&lt;/p&gt;
&lt;pre class="literal-block"&gt;
00000000  00 01 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
*
00000050  ff ff ff ff ff ff ff ff  ff ff ff ff 00 30 21 30
00000060  09 06 05 2b 0e 03 02 1a  05 00 04 14 00 00 00 00
00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
&lt;/pre&gt;
&lt;p&gt;and copy the sha1 at offset &lt;tt class="docutils literal"&gt;0x6c&lt;/tt&gt;. (yes PKCS1 scheme).&lt;/p&gt;
&lt;p&gt;It then rsa-decode the passed &lt;tt class="docutils literal"&gt;0x80&lt;/tt&gt; long signature with an hardcoded public key and memcompare the result to the built structure.
No asn1 parsing of the provided signature, so no chance to find a pkcs bleichenbacher like attack...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="back-to-basis"&gt;
&lt;h2&gt;Back to basis&lt;/h2&gt;
&lt;p&gt;At this point, It was like a deja vu:&lt;/p&gt;
&lt;img alt="" src="/medias/rsa.png" /&gt;
&lt;p&gt;(sha1 this time, but hey, even if sha1 collision are real, not preimage attacks)&lt;/p&gt;
&lt;p&gt;But after more digging:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;probably_load_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;bootloader_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local_60&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;DAT_bf400888&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xa0500000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;local_60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0xa0500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x4c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;DAT_bf40088c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;local_60&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;percello_sig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xa0500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;local_60&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;percello_sg_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;DAT_bf40090c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;local_60&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fm_sig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xa0500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;local_60&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fm_sig_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;DAT_bf400880&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local_60&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;percello_sig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;DAT_bf400884&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local_60&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fm_sig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;0xa0500000&lt;/tt&gt; is probably the location of the tftp-loaded image. So this function maps the file header and...&lt;/p&gt;
&lt;p&gt;Wait ! memcpy a user provided buffer (&lt;tt class="docutils literal"&gt;fm_sig&lt;/tt&gt; at a known location (&lt;tt class="docutils literal"&gt;0xbf40090c&lt;/tt&gt;), with a user provided length (&lt;tt class="docutils literal"&gt;fm_sig_len&lt;/tt&gt;)?&lt;/p&gt;
&lt;p&gt;And below the stack (&lt;tt class="docutils literal"&gt;0xbf403ff0&lt;/tt&gt;) ?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# init stack pointer&lt;/span&gt;
&lt;span class="nf"&gt;lui&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0xbf40&lt;/span&gt;
&lt;span class="nf"&gt;ori&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="no"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0x3ff0&lt;/span&gt;
&lt;span class="nf"&gt;addiu&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="no"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0x0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Time for a good old stack smashing (for fun and profit)!&lt;/p&gt;
&lt;p&gt;After a few time, found the right len to smash &lt;tt class="docutils literal"&gt;ra&lt;/tt&gt; in the memcpy call on the stack, and jump just after the signature verification. Also needed to keep some values in ram, so my buffer overflow was not only full of &lt;tt class="docutils literal"&gt;0xff&lt;/tt&gt; and I was able to successfully jump to the percello bootloader, without signature verification.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Node-H FM-loader v1.2
booting in ******* mode
changing CPU frequency... done
image verification bypass!
copying initrd at 0X8F6C8000...
&lt;/pre&gt;
&lt;p&gt;Then all was left was patching percello bootloader to skip FM-loader verification:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Node-H FM-loader v1.2
booting in Xilokar mode
changing CPU frequency... done
image verification success
copying initrd at 0X8F6C8000...
copying kernel...
bytes: 3338752
&lt;/pre&gt;
&lt;p&gt;And then patching FM-loader to allow for arbitrary kernels and initrd:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Node-H FM-loader v1.2
booting in Xilokar mode
changing CPU frequency... done
image verification bypass!
copying initrd at 0X8F6C8000...
copying kernel...
bytes: 3338752
booting kernel...
[    0.000000] Linux version 2.6.31.12-Percello-1.12-9
...
[    1.633762] Freeing unused kernel memory: 152k freed

==================================================================
Welcome to Percello Root File System Version R2.4  (not so) Secure
Pwned by Xilokar
==================================================================
---- Mounting proc file system
Sat Aug  1 00:00:00 UTC 2015
---- Mounting ramdisk with size 32M
---- Remounting /dev/root
---- Starting syslogd
---- Mounting sysfs
---- Mounting devpts
---- Creating loopback device
---- Activating Ethernet device
&lt;/pre&gt;
&lt;p&gt;(I realize I did not talk about understanding firmware image structure)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Unpatchable (ROM) secure boot bypass on bcm61650.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Misc"></category><category term="Reverse"></category></entry><entry><title>Time to reverse - Part 1/x</title><link href="https://blog.xilokar.info/time-to-reverse-part-1x.html" rel="alternate"></link><published>2018-03-06T00:00:00+01:00</published><updated>2018-03-06T00:00:00+01:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2018-03-06:/time-to-reverse-part-1x.html</id><summary type="html">&lt;p&gt;After some time spent, I've finally managed to identify the jtag pins on my MC9620 "phone".&lt;/p&gt;
&lt;img alt="" src="/medias/jtag.jpg" style="width: 100%;"/&gt;
</summary><content type="html">&lt;p&gt;After some time spent, I've finally managed to identify the jtag pins on my MC9620 &amp;quot;phone&amp;quot;.&lt;/p&gt;
&lt;img alt="" src="/medias/jtag.jpg" style="width: 100%;" /&gt;

&lt;p&gt;It looks obvious once found...&lt;/p&gt;
&lt;p&gt;Unfortunately, I think I have fried the device while doing so.&lt;/p&gt;
&lt;p&gt;Nevertheless, I've successfully dump the firmware of the phone, so now, it is time to fire up radare2 and try to extract some usefull information from the dump. But it will surely be a very hard and slow journey.&lt;/p&gt;
&lt;img alt="" src="/medias/0x00800000.jpg" style="width: 100%;" /&gt;
&lt;p&gt;And I have to find another device, if I want to be able to speed up the process.&lt;/p&gt;
</content><category term="Misc"></category><category term="Reverse"></category><category term="Tetrapol"></category><category term="MC9620"></category></entry><entry><title>It Didn't Work</title><link href="https://blog.xilokar.info/it-didnt-work.html" rel="alternate"></link><published>2018-01-11T00:00:00+01:00</published><updated>2018-01-11T00:00:00+01:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2018-01-11:/it-didnt-work.html</id><content type="html">&lt;p&gt;A picture is worth a thousand words...&lt;/p&gt;
&lt;img alt="&amp;quot;It didn't work&amp;quot;" src="/medias/ItDidNotWork.png" /&gt;
</content><category term="Misc"></category></entry><entry><title>Video Distorsion</title><link href="https://blog.xilokar.info/video-distorsion.html" rel="alternate"></link><published>2017-04-10T00:00:00+02:00</published><updated>2017-04-10T00:00:00+02:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2017-04-10:/video-distorsion.html</id><content type="html">&lt;p&gt;Found this old piece of code, written in 2013. Only needed to change hardcoded resolution of the webcam to get it working again.&lt;/p&gt;
&lt;video controls poster=medias/TimeDistortion.jpg&gt;
&lt;source src="medias/TimeDistortion.mp4" type="video/mp4"&gt;
&lt;source src="medias/TimeDistortion.ogg" type="video/ogg"&gt;
&lt;/video&gt;&lt;!--  --&gt;
</content><category term="Misc"></category></entry><entry><title>Hello World</title><link href="https://blog.xilokar.info/hello-world.html" rel="alternate"></link><published>2015-04-17T00:00:00+02:00</published><updated>2015-04-17T00:00:00+02:00</updated><author><name>Xilokar</name></author><id>tag:blog.xilokar.info,2015-04-17:/hello-world.html</id><content type="html">&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;!--  --&gt;
</content><category term="Misc"></category></entry></feed>