{"id":4682,"date":"2024-11-13T10:10:51","date_gmt":"2024-11-13T09:10:51","guid":{"rendered":"https:\/\/security.humanativaspa.it\/?p=4682"},"modified":"2025-09-11T07:20:27","modified_gmt":"2025-09-11T07:20:27","slug":"fault-injection-down-the-rabbit-hole","status":"publish","type":"post","link":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/","title":{"rendered":"Fault Injection &#8211; Down the Rabbit Hole"},"content":{"rendered":"<h3>Intro<\/h3>\n<p>This <a href=\"https:\/\/hnsecurity.it\/tag\/fault-injection\">series<\/a> of articles describes <strong>fault injection attack techniques<\/strong> in order to understand their real potential by testing their limits and applicability with limited hardware (available on the market at an acceptable cost). It explores possible ways of using an attack that, in my opinion, is <strong>greatly underestimated<\/strong>.<\/p>\n<p>First of all, I want to thank <a href=\"https:\/\/twitter.com\/pulsoid\">@pulsoid<\/a> and <a href=\"https:\/\/twitter.com\/tieknimmers\">@tieknimmers<\/a> for their excellent <em>Fault inject advanced<\/em> course (<a href=\"https:\/\/raelize.com\/taofi\/\">TAoFI &#8211; The Art of Fault Injection<\/a>) that I attended. In their training, they provide great insights and ideas, thanks to their pioneering work and passionate pursuit of these topics. One of the mantras of the course was &#8220;<strong>Don&#8217;t glitch and pray<\/strong>&#8221; (\u00a9 <a href=\"https:\/\/raelize.com\/\">Raelize<\/a>), and I tried to internalize this concept as much as possible. These articles were born precisely from that.<\/p>\n<p>The term <em>glitching<\/em>\u00a0refers to an <strong>external behavior that causes a chip to enter an anomalous state<\/strong>, allowing for the <strong>creation of a fault<\/strong>, which is an internal error that enables the execution of something different from what was expected. Let&#8217;s start with the basics. There are four main techniques for performing fault injection on a chip:<\/p>\n<ul>\n<li><strong>Voltage glitching<\/strong><\/li>\n<li><strong>Clock glitching<\/strong><\/li>\n<li><strong>Electromagnetic glitching<\/strong><\/li>\n<li><strong>Optical glitching (laser)<\/strong><\/li>\n<\/ul>\n<p>I will focus on the voltage glitching part, as it is one of the most approachable techniques with limited hardware. The basic concept is that we &#8220;deprive&#8221; the chip of power, making it &#8220;unstable&#8221;.<\/p>\n<p>There are several ways to perform voltage glitching, primarily:<\/p>\n<ul>\n<li>Crowbar to ground (used by ChipWhisperer)<\/li>\n<li>Crowbar to high voltage (which risks burning the chip)<\/li>\n<li>Controlled VCC (by providing a controlled different voltage)<\/li>\n<\/ul>\n<p>For now, we will use the <strong>crowbar to ground<\/strong> technique, which is used by <a href=\"https:\/\/www.newae.com\/chipwhisperer\">ChipWhisperer<\/a>\u00a0devices. During the tests, I mainly used <a href=\"https:\/\/rtfm.newae.com\/Capture\/ChipWhisperer-Husky\/\">ChipWhisperer-Husky<\/a>. A detailed description of the technique can be found at: <a href=\"https:\/\/eprint.iacr.org\/2016\/810.pdf\">https:\/\/eprint.iacr.org\/2016\/810.pdf<\/a><\/p>\n<p>As for the target of these attacks, I have chosen to work on <strong>ESP32<\/strong> for various reasons, primarily:<\/p>\n<ul>\n<li>There is already a lot of available material on attacks.<\/li>\n<li>There is a &#8220;patched&#8221; v3 chip that should solve multiple issues on which it will be possible to test the resistance of the countermeasures implemented.<\/li>\n<li>It was the chip used in the TaoFI course, so I already have a working board ready.<\/li>\n<\/ul>\n<p>The main <strong>past works<\/strong> on these chips are the following (hoping to mention them all):<\/p>\n<ul>\n<li>Pwn the ESP32 Secure Boot <a href=\"https:\/\/limitedresults.com\/2019\/09\/pwn-the-esp32-secure-boot\/\">https:\/\/limitedresults.com\/2019\/09\/pwn-the-esp32-secure-boot\/<\/a><\/li>\n<li>Pwn the ESP32 Forever: Flash Encryption and Sec. Boot Keys Extraction <a href=\"https:\/\/limitedresults.com\/2019\/11\/pwn-the-esp32-forever-flash-encryption-and-sec-boot-keys-extraction\/\">https:\/\/limitedresults.com\/2019\/11\/pwn-the-esp32-forever-flash-encryption-and-sec-boot-keys-extraction\/<\/a> + <a href=\"https:\/\/www.youtube.com\/watch?v=vwwTC_ivG00\">https:\/\/www.youtube.com\/watch?v=vwwTC_ivG00<\/a><\/li>\n<li>Espressif ESP32: Bypassing Secure Boot using EMFI <a href=\"https:\/\/raelize.com\/blog\/espressif-systems-esp32-bypassing-sb-using-emfi\/\">https:\/\/raelize.com\/blog\/espressif-systems-esp32-bypassing-sb-using-emfi\/<\/a><\/li>\n<li>Espressif ESP32: Controlling PC during Secure Boot <a href=\"https:\/\/raelize.com\/blog\/espressif-systems-esp32-controlling-pc-during-sb\/\">https:\/\/raelize.com\/blog\/espressif-systems-esp32-controlling-pc-during-sb\/<\/a><\/li>\n<li>Espressif ESP32: Bypassing Flash Encryption (CVE-2020-15048) <a href=\"https:\/\/raelize.com\/blog\/espressif-systems-esp32-bypassing-flash-encryption\/\">https:\/\/raelize.com\/blog\/espressif-systems-esp32-bypassing-flash-encryption\/<\/a><\/li>\n<li>Espressif ESP32: Bypassing Encrypted Secure Boot (CVE-2020-13629) <a href=\"https:\/\/raelize.com\/blog\/espressif-esp32-bypassing-encrypted-secure-boot-cve-2020-13629\/\">https:\/\/raelize.com\/blog\/espressif-esp32-bypassing-encrypted-secure-boot-cve-2020-13629\/<\/a><\/li>\n<li>Unlimited Results: Breaking Firmware Encryption of ESP32-V3 <a href=\"https:\/\/eprint.iacr.org\/2023\/090.pdf\">https:\/\/eprint.iacr.org\/2023\/090.pdf<\/a> + <a href=\"https:\/\/www.youtube.com\/watch?v=wfZHQocTsZo\">https:\/\/www.youtube.com\/watch?v=wfZHQocTsZo<\/a><\/li>\n<li>Breaking the Flash Encryption Feature of Espressif\u2019s Parts <a href=\"https:\/\/courk.cc\/breaking-flash-encryption-of-espressif-parts\">https:\/\/courk.cc\/breaking-flash-encryption-of-espressif-parts<\/a><\/li>\n<li>Fault Injection Attacks against the ESP32-C3 and ESP32-C6 <a href=\"https:\/\/courk.cc\/esp32-c3-c6-fault-injection\">https:\/\/courk.cc\/esp32-c3-c6-fault-injection<\/a><\/li>\n<li>Breaking Espressif\u2019s ESP32 V3: Program Counter Control with Computed Values using Fault Injection <a href=\"https:\/\/www.usenix.org\/conference\/woot24\/presentation\/delvaux\">https:\/\/www.usenix.org\/conference\/woot24\/presentation\/delvaux<\/a><\/li>\n<\/ul>\n<p>I encourage you to read them to get familiar with the topic, otherwise you will likely struggle to understand the rest of this article.<\/p>\n<h3>Let&#8217;s start<\/h3>\n<p>Let&#8217;s now try to create a &#8220;clean&#8221; situation that allows us to better explore what happens with glitching.<\/p>\n<p><strong>Unlike many examples found online, our goal is not to skip an instruction but to understand what else can happen and why. Thus, trying to make a &#8220;world&#8221; considered non-deterministic a little more deterministic.<\/strong><\/p>\n<p>To do this, we need to:<\/p>\n<ul>\n<li>understand exactly which instruction(s) we are going to influence<\/li>\n<li>know the context (including other registers, memory areas, etc.)<\/li>\n<\/ul>\n<p>So:<\/p>\n<ul>\n<li>we need to use as much <strong>ASM code as possible instead of C code in order to exclude unnecessary instructions<\/strong> (e.g., calls) that partially modify the context<\/li>\n<li>find a method to have a <strong>clear view of the context without influencing it<\/strong><\/li>\n<li>use a limited number of instructions, especially ones that allow us to understand which one we are influencing<\/li>\n<\/ul>\n<h3>Preparation of the test environment<\/h3>\n<h4>Using as few instructions as possible<\/h4>\n<p>Now let&#8217;s try to create an environment that is as clean as possible, and see how to improve the code that is normally used as a starting point.<\/p>\n<p>Generally, when working on glitching examples, a <strong>trigger signal<\/strong> is used, which is when the code of our interest is executed. This helps us explore the data more precisely by narrowing down the scope.<\/p>\n<p>This method is often used to change a trigger PIN:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">GPIO_OUTPUT_SET(26,1);\r\n<\/pre>\n<p>However, if we look at how this is translated at the assembler level, it generates:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20231122184428-2-1.png\" alt=\"Pasted image 20231122184428.png\" \/><\/p>\n<p>Essentially, the function &#8220;0x40009B24&#8221; (gpio_output_set) is called, which is present in the ROM. By disassembling the ROM, we can see what happens:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20231121225520-2-1.png\" alt=\"Pasted image 20231121225520.png\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20231121225803-2-1.png\" alt=\"Pasted image 20231121225803.png\" \/><\/p>\n<p>In the documentation, you can find details about the addresses used:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20231121225741-2-1.png\" alt=\"Pasted image 20231121225741.png\" \/><\/p>\n<p>And, more specifically:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20231121225917-2-1.png\" alt=\"Pasted image 20231121225917.png\" \/><\/p>\n<p>According to the reference manual, we can use GPIO_OUT_W1TS_REG to activate the pin and GPIO_OUT_W1TC_REG to deactivate it, thus eliminating a call and a series of unnecessary instructions that could cause problems during glitching.<\/p>\n<p>The final assembler code will be:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\/\/ GPIO 26 PING HIGH using GPIO_OUT_W1TS\r\n\"movi a11, 0x4000000;\"\r\n\"movi a12, 0x3ff44008;\"\r\n\"s32i.n  a11, a12, 0;\"\r\n\r\n\/\/ GPIO 26 PIN LOW using GPIO_OUT_W1TC\r\n\"movi a12, 0x3ff4400C;\"\r\n\"movi a11, 0x4000000;\"\r\n\"s32i.n  a11, a12, 0;\"\r\n<\/pre>\n<p>This way, we save instructions and tamper only with a very limited number of registers.<\/p>\n<h4>Having a clear understanding of the context<\/h4>\n<p>Once we have solved the initial problem, we need to find a simple way to maintain the context while <strong>losing as little information as possible<\/strong>.<\/p>\n<p>My idea is to <strong>use CPU exceptions that allow to get a complete context<\/strong> (https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-guides\/fatal-errors.html#illegal-instr-msg). The initial idea was to execute the code at the bootloader level to &#8220;speed up&#8221; the boot phase. However, the exceptions are directly handled by the ROM, and the classic &#8220;Guru meditation&#8221; has not been implemented yet:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819215208-2-1.png\" alt=\"Pasted image 20240819215208.png\" \/><\/p>\n<p>The advantage is having a complete context, but the downside is that each attempt would require resetting the CPU, resulting in fewer tests. However, at this moment, I prefer to have a clearer understanding of what is happening rather than being fast.<\/p>\n<p>After conducting a search, I found out that the ROM uses the following code:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20231122105303-2-1.png\" alt=\"Pasted image 20231122105303.png\" \/><\/p>\n<p>During boot, it sets up a series of exception handlers that point to a function that prints some information. However, these exceptions only provide partial information and are only available for certain types.<\/p>\n<p>I have made various attempts to correctly implement the complete <strong>exception handlers<\/strong>, and it is possible, but not straightforward. The code that should be implemented is the same as the one already present in <strong>FreeRTOS<\/strong>:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/espressif\/esp-idf\/blob\/ab03c2ea13ecaac1510b75e93b32cf0c472640fb\/components\/esp_system\/port\/panic_handler.c#L208\">https:\/\/github.com\/espressif\/esp-idf\/blob\/ab03c2ea13ecaac1510b75e93b32cf0c472640fb\/components\/esp_system\/port\/panic_handler.c#L208<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/espressif\/esp-idf\/blob\/ab03c2ea13ecaac1510b75e93b32cf0c472640fb\/components\/esp_system\/port\/arch\/xtensa\/panic_handler_asm.S#L18\">https:\/\/github.com\/espressif\/esp-idf\/blob\/ab03c2ea13ecaac1510b75e93b32cf0c472640fb\/components\/esp_system\/port\/arch\/xtensa\/panic_handler_asm.S#L18<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/espressif\/esp-idf\/blob\/ab03c2ea13ecaac1510b75e93b32cf0c472640fb\/components\/xtensa\/xtensa_context.S#L71\">https:\/\/github.com\/espressif\/esp-idf\/blob\/ab03c2ea13ecaac1510b75e93b32cf0c472640fb\/components\/xtensa\/xtensa_context.S#L71<\/a><\/li>\n<\/ul>\n<p>For this reason, I preferred to have the original bootloader that implements FreeRTOS and already has all the exception handlers implemented.<\/p>\n<p>To generate the exception, we have different methods, the simplest one being to perform a write to a non writable area:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\"movi a13, 0x93939393;\"\r\n\"s32i.n  a2, a13, 0;\"\r\n<\/pre>\n<p>This way, when necessary, with just one instruction, we will be able to see the complete context. <strong>Furthermore, using a unique method for all types of faults will allow us to perform a unified parsing in all situations and quickly identify if the injected glitch has allowed the instructions to continue until the end of the code.<\/strong><\/p>\n<h4>Instructions to attack<\/h4>\n<p>The standard fault injection example uses <strong>loops or similar methods that do not allow us to understand in detail what is happening, thus it&#8217;s not an optimal approach<\/strong>. Instead, repeated instructions are arguably the best choice. However, in this case, we also want to <strong>understand precisely which ones we are affecting<\/strong>. By using a different increment value each time, we can understand which instruction we are influencing and what happens.<\/p>\n<p>To determine which instruction we are affecting, we add a number that is equivalent to a single bit representation. This will speed up certain types of analysis:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\"addi a6, a6, 0x1;\"\r\n\"addi a6, a6, 0x2;\"\r\n\"addi a6, a6, 0x4;\"\r\n\"addi a6, a6, 0x8;\"\r\n\"addi a6, a6, 0x10\"\r\n\"addi a6, a6, 0x20\"\r\n\"addi a6, a6, 0x40;\"\r\n<\/pre>\n<p>The result of the operations will be as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\"addi a6, a6, 0x1;\"  -&gt; a6 = 0x01 (0b00000001)\r\n\"addi a6, a6, 0x2;\"  -&gt; a6 = 0x03 (0b00000011)\r\n\"addi a6, a6, 0x4;\"  -&gt; a6 = 0x07 (0b00000111)\r\n\"addi a6, a6, 0x8;\"  -&gt; a6 = 0x0F (0b00001111)\r\n\"addi a6, a6, 0x10\"  -&gt; a6 = 0x1F (0b00011111)\r\n\"addi a6, a6, 0x20\"  -&gt; a6 = 0x3F (0b00111111)\r\n\"addi a6, a6, 0x40;\" -&gt; a6 = 0x7F (0b01111111)\r\n<\/pre>\n<p>As a safety measure, we also check with IDA Pro that the code generated by the compiler is what we intended it to be:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20231201124427-2-1.png\" alt=\"Pasted image 20231201124427.png\" \/><\/p>\n<p>As we can see, probably <strong>due to some assembler optimizations, the code has been partially changed<\/strong>. In fact, the first instructions have been translated as &#8220;addi.n,&#8221; which are 16-bit instructions, instead of &#8220;addi,&#8221; which are 24-bit instructions. In terms of code functionality, the result remains unchanged, as the two instructions are equivalent.<\/p>\n<p>By researching details in the &#8220;Xtensa Instruction Set Architecture (ISA) &#8211; Reference Manual,&#8221; we can find the following:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Assembler Note\r\nThe assembler may convert ADDI instructions to ADDI.N when the Code Density\r\nOption is enabled and the immediate operand falls within the available range. If the immediate\r\nis too large the assembler may substitute an equivalent sequence. Prefixing the\r\nADDI instruction with an underscore (_ADDI) disables these optimizations and forces\r\nthe assembler to generate the wide form of the instruction or an error instead.\r\n<\/pre>\n<p>By modifying the assembly code as described at this point (replacing ADDI with _ADDI), we would get the &#8220;clean&#8221; code, which is also confirmed by the disassembling:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20231215224519-2-1.png\" alt=\"Pasted image 20231215224519.png\" \/><\/p>\n<p>By conducting some tests, we found that approximately 12 instructions are executed in about 162ns. Considering that the compilation options set the frequency to 80Mhz and assuming that each instruction requires approximately 2 clock cycles, the timing looks reasonable:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240809153534-2-1.png\" alt=\"Pasted image 20240809153534.png\" \/><\/p>\n<p>Using a frequency of 160Mhz, we have approximately 62 nanoseconds for the execution of 12 instructions:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20231201130259-2-1.png\" alt=\"Pasted image 20231201130259.png\" \/><\/p>\n<p>For convenience, let&#8217;s start working at 80Mhz to be more precise.<\/p>\n<h4>Putting everything together<\/h4>\n<p>To have a completely controlled environment, we need to perform the following steps:<\/p>\n<ul>\n<li>Set all registers to known values. This will help us understand what is happening.:<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\/\/ a0 is return address, but not used anymore\r\n\"movi a0, 0x40404040;\"\r\n\r\n\/\/ a1 is the stack pointer (it's not a typo, I decided to exclude the a1 to have clean info into the stacktraces)\r\n\/\/ \"movi a0, 0x41414141;\"\r\n\r\n\"movi a2, 0x42424242;\"\r\n\"movi a3, 0x43434343;\"\r\n\"movi a4, 0x44444444;\"\r\n\"movi a5, 0x45454545;\"\r\n\"movi a6, 0x46464646;\"\r\n\"movi a7, 0x47474747;\"\r\n\"movi a8, 0x48484848;\"\r\n\"movi a9, 0x49494949;\"\r\n\"movi a10, 0x50505050;\"\r\n\"movi a11, 0x51515151;\"\r\n\"movi a12, 0x52525252;\"\r\n\"movi a13, 0x93939393;\"\r\n\"movi a14, 0x54545454;\"\r\n\"movi a15, 0x55555555;\"\r\n<\/pre>\n<ul>\n<li>Set the trigger:<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\/\/ GPIO 26 PING HIGH using GPIO_OUT_W1TS\r\n\"movi a11, 0x4000000;\"\r\n\r\n\"movi a12, 0x3ff44024;\"\r\n\"s32i.n  a11, a12, 0;\"\r\n\r\n\"movi a12, 0x3ff44008;\"\r\n\"s32i.n  a11, a12, 0;\"\r\n<\/pre>\n<ul>\n<li>Modify the registers used during the trigger setup:<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\/\/ Set correctly used registers\r\n\"movi a11, 0x51515151;\"\r\n\"movi a12, 0x52525252;\"\r\n<\/pre>\n<ul>\n<li>Execute a series of NOPs to allow time for glitching and propagation:<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\/\/ Execute NOP instructions\r\n\"nop;\"\r\n<\/pre>\n<ul>\n<li>Execute the code we want to attack:<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\"addi a6, a6, 0x1;\"\r\n\"addi a6, a6, 0x2;\"\r\n\"addi a6, a6, 0x4;\"\r\n\"addi a6, a6, 0x8;\"\r\n\"addi a6, a6, 0x10;\"\r\n\"addi a6, a6, 0x20;\"\r\n\"addi a6, a6, 0x40;\"\r\n<\/pre>\n<ul>\n<li>Execute a second series of NOPs to avoid glitching the final exception creation:<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\/\/ Execute NOP instructions\r\n\"nop;\"\r\n<\/pre>\n<ul>\n<li>Set the trigger again to deactivate it:<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\/\/ GPIO 26 PIN LOW using GPIO_OUT_W1TC\r\n\"movi a12, 0x3ff4400C;\"\r\n\"movi a11, 0x4000000;\"\r\n\"s32i.n  a11, a12, 0;\"\r\n<\/pre>\n<ul>\n<li>Generate a CPU exception:<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"asm\">\/\/ GENERATE CPU EXCEPTION\r\n\"s32i.n  a2, a13, 0;\"\r\n<\/pre>\n<p>By running the entire code, we can observe that execution takes around a total of 25,200 nanoseconds:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240809153608-2-1.png\" alt=\"Pasted image 20240809153608.png\" \/><\/p>\n<h3>Glitching<\/h3>\n<h4>Hardware setup<\/h4>\n<p>On the datasheet of the ESP32 processor, further details can be found on how the different VDD pins that provide power to the chip are used:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240809150151-2-1.png\" alt=\"Pasted image 20240809150151.png\" \/><\/p>\n<p>For this initial analysis, I decided to keep <strong>all VDD pins connected together<\/strong>, removing the capacitors connected to the VDD3P3_RTC and VDD3P3_CPU power lines.<\/p>\n<p>The hardware on which the tests were performed has the following configuration, and the circled capacitors have been removed:<\/p>\n<p><img decoding=\"async\" class=\"\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819213918-2-1.png\" alt=\"Pasted image 20240819213918.png\" width=\"645\" height=\"333\" \/><\/p>\n<p>Source: <a href=\"https:\/\/github.com\/raelize\/TAoFI-Target\/blob\/main\/files\/schematic.png\">https:\/\/github.com\/raelize\/TAoFI-Target\/blob\/main\/files\/schematic.png<\/a><\/p>\n<h4>Glitching preparation<\/h4>\n<p>Now that we have a &#8220;clean&#8221; environment just the way I like it, let&#8217;s look at the main features of the <strong>glitching script<\/strong>.<\/p>\n<p>For convenience, we use the setup provided during the course, which includes:<\/p>\n<ul>\n<li>an ESP-PROG programmer with which we communicate via serial to the ESP32<\/li>\n<li>a Chipwhisperer Husky connected to the trigger PIN and responsible for performing crowbar glitching<\/li>\n<li>an RK6006 power supply to provide the ESP32 with a controlled voltage below the standard, making it more comfortable to execute faults; throughout all the tests, the power supply provides 2.13v to the ESP32 chip, which is below the threshold recommended by the manufacturer<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240129230604-2-1.png\" alt=\"Pasted image 20240129230604.png\" \/><\/p>\n<p>After some initial tests, I have determined that the probable values for obtaining a good sample are as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">min_length = 400 \u00a0 \u00a0\r\nmax_length = 3000\r\nmin_delay = 4000\r\nmax_delay = 22000\r\n<\/pre>\n<p>To begin, we will use a &#8220;standard&#8221; configuration of the Husky:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">cw_scope.clock.clkgen_src \u00a0 \u00a0 \u00a0 \u00a0 \u00a0= 'system'\r\ncw_scope.clock.adc_mul \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 = 1\r\ncw_scope.clock.clkgen_freq \u00a0 \u00a0 \u00a0 \u00a0 = 200e6\r\n\r\n# Glitching parameters\r\ncw_scope.io.glitch_hp \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0= True\r\ncw_scope.io.glitch_lp \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0= False\u00a0 \u00a0 \r\n<\/pre>\n<p>In the following articles of this <a href=\"https:\/\/hnsecurity.it\/tag\/fault-injection\">series<\/a>, we will also explore how we can make the most of the Husky.<\/p>\n<p>However, the most important part is the <strong>initial classification<\/strong> that is performed before saving the result.<\/p>\n<p>As we described earlier, we know that all the results should be &#8220;identical&#8221; because we use CPU exceptions that are all handled in the same way, whether our glitch is too long, causing an illegal instruction, or our glitch is too short and therefore does not affect code execution.<\/p>\n<p>A specific routine is responsible for analyzing the result, comparing it with the expected result, and <strong>saving only the values that are &#8220;different&#8221; from the standard ones, in order to have a cleaner output during subsequent analysis.<\/strong><\/p>\n<h3>A first interpretation of the results<\/h3>\n<p>With the &#8220;Glitch and pray&#8221; approach, we can start to see the first results and try to understand how to interpret them better. We have two varying values: the distance of the glitch from the trigger (delay) and the length of the performed glitch (length).<\/p>\n<p>Some <strong>important assumptions<\/strong>:<\/p>\n<ul>\n<li>If PC is different from 0x400d713b (the address of the last instruction before the forged exception), we have not experienced a &#8220;clean&#8221; fault, so something broke beforehand. In the case of &#8220;illegal instruction&#8221; exceptions, it could help us understand which instruction caused the fault.<\/li>\n<li>If PC is equal to 0x400d713b (the address of the last instruction before the forged exception), we can interpret the results and understand which instructions we have influenced.<\/li>\n<li>All our target code works on the A6 registry; if A6 has not changed it is very likely that we have influenced instructions that are not of our interest.<\/li>\n<\/ul>\n<p>All the <strong>results have been classified<\/strong> in this way:<\/p>\n<ul>\n<li>the green color represents &#8220;normal&#8221; results, the PC is correct and no modification of others registers has been detected<\/li>\n<li>the magenta color represents CPU restarts that usually happen if the glitch is too long<\/li>\n<li>the yellow color represents a fault with wrong PC, which means that we didn&#8217;t reach our final code<\/li>\n<li>the cyan color represents a fault where PC is correct (we reached our last instruction) and also A6 is correct, which means we didn&#8217;t fault our target instruction, but some other instruction<\/li>\n<li>the red color represents a fault where PC is correct (we reached our last instruction) and A6 doesn&#8217;t have the proper value, which means we faulted our target instruction<\/li>\n<\/ul>\n<p>After 36K attempts, here are the first results:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128233433-2-1.png\" alt=\"Pasted image 20240128233433.png\" \/><\/p>\n<p>The ones of interest to us are the red dots, where we have the correct PC but A6 doesn&#8217;t have the value we expected.<\/p>\n<p>By cleaning up the results a little bit, we can see how the areas are quite concentrated:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128233745-2-1.png\" alt=\"Pasted image 20240128233745.png\" \/><\/p>\n<p>We can find in blue some points of particular interest to us. For example, the &#8220;illegal instruction&#8221; in the first add operation. We can associate this behavior with &#8220;we have zeroed too many bits&#8221; of a specific instruction.<\/p>\n<p>Searching for results <code>Illegal.*PC: 0x400d70e4<\/code> we can identify parameters which lead us to corrupt our first target instruction which is at 0x400d70e4:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234155-2-1.png\" alt=\"Pasted image 20240128234155.png\" \/><\/p>\n<p>Looking for <code>Illegal.*PC: 0x400d70e7<\/code> we can identify parameters which lead to corrupt the second instruction:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234241-2-1.png\" alt=\"Pasted image 20240128234241.png\" \/><\/p>\n<p>Looking for <code>Illegal.*PC: 0x400d70ea<\/code> we can identify parameters which lead to corrupt the third instruction:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234302-2-1.png\" alt=\"Pasted image 20240128234302.png\" \/><\/p>\n<p>Looking for <code>Illegal.*PC: 0x400d70ed<\/code> we can identify parameters which lead to corrupt the fourth instruction:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234322-2-1.png\" alt=\"Pasted image 20240128234322.png\" \/><\/p>\n<p>Looking for <code>Illegal.*PC: 0x400d70f0<\/code> we can identify parameters which lead to corrupt the fourth instruction:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234353-2-1.png\" alt=\"Pasted image 20240128234353.png\" \/><\/p>\n<p>Looking for <code>Illegal.*PC: 0x400d70f3<\/code> we can identify parameters which lead to corrupt the fifth instruction:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234407-2-1.png\" alt=\"Pasted image 20240128234407.png\" \/><\/p>\n<p>Looking for <code>Illegal.*PC: 0x400d70f6<\/code> we can identify parameters which lead to corrupt the sixth instruction:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234434-2-1.png\" alt=\"Pasted image 20240128234434.png\" \/><\/p>\n<p>Executing some custom query on the data we can also find where we &#8220;skipped the instruction&#8221; (we will see later that this is not actually the case) by looking for the expected value in A6.<\/p>\n<p>Looking for <code>Store.* PC: 0x400d713b.*A6 : 0x0000007e<\/code> we can identify parameters which lead to corrupt the first instruction in a way that the additional operation has not been executed:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234752-2-1.png\" alt=\"Pasted image 20240128234752.png\" \/><\/p>\n<p>Looking for <code>Store.* PC: 0x400d713b.*A6 : 0x0000007d<\/code> we can identify parameters which lead to corrupt the second instruction in a way that the additional operation has not been executed. In our initial test, no cases have been identified:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234818-2-1.png\" alt=\"Pasted image 20240128234818.png\" \/><\/p>\n<p>Looking for <code>Store.* PC: 0x400d713b.*A6 : 0x0000007b<\/code> we can identify parameters which lead to corrupt the third instruction in a way that the additional operation has not been executed:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234841-2-1.png\" alt=\"Pasted image 20240128234841.png\" \/><\/p>\n<p>Looking for <code>Store.* PC: 0x400d713b.*A6 : 0x00000077<\/code> we can identify parameters which lead to corrupt the forth instruction in a way that the additional operation has not been executed:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234858-2-1.png\" alt=\"Pasted image 20240128234858.png\" \/><\/p>\n<p>Looking for <code>Store.* PC: 0x400d713b.*A6 : 0x0000006f<\/code> we can identify parameters which lead to corrupt the fifth instruction in a way that the additional operation has not been executed:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234918-2-1.png\" alt=\"Pasted image 20240128234918.png\" \/><\/p>\n<p>Looking for <code>Store.* PC: 0x400d713b.*A6 : 0x0000005f<\/code> we can identify parameters which lead to corrupt the sixth instruction in a way that the additional operation has not been executed:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128234941-2-1.png\" alt=\"Pasted image 20240128234941.png\" \/><\/p>\n<p>Looking for <code>Store.* PC: 0x400d713b.*A6 : 0x0000003f<\/code> we can identify parameters which lead to corrupt the seventh instruction in a way that the additional operation has not been executed:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240128235000-2-1.png\" alt=\"Pasted image 20240128235000.png\" \/><\/p>\n<p><strong>As we could see from the initial results, we can consider performing a very precise targeting of an instruction based on the time from the trigger.<\/strong><\/p>\n<p><strong>However, the same results tell us that some instructions are more &#8220;simple&#8221; to target than others. I hypothesize that this is also due to the pipeline and internal caches of the processor.<\/strong><\/p>\n<h3>A script to better understand the cause<\/h3>\n<p>One of the fundamental things taught in the course by <a href=\"https:\/\/twitter.com\/pulsoid\">@pulsoid<\/a> and <a href=\"https:\/\/twitter.com\/tieknimmers\">@tieknimmers<\/a> is to debunk the myth of &#8220;an instruction was skipped&#8221;. Many who talk about glitching and fault injection wrongly use this term just to say &#8220;I didn&#8217;t understand what happened&#8221;.<\/p>\n<p>To understand the results we are going to analyze, we need to hypothesize what will happen at the processor level. Since we are using the &#8220;crowbar to ground&#8221; technique, it is <strong>plausible to assume that during certain CPU operations<\/strong> (such as loading instructions, execution, memory copies, etc.), <strong>some bits which are 1 may turn into 0<\/strong>. Other techniques could yield different results, but this is the most likely effect in our situation.<\/p>\n<p>To do this, I have developed a small script that, given a specific opcode, sets N bits to 0 and observes what the &#8220;corrupted&#8221; instruction would be. In an ideal world, fault injection could change a single bit, but currently we do not know if we can be that precise. Therefore, we must assume that we will change N different bits.<\/p>\n<p>The script generates N different possibilities by assuming influence on N different bits. The bits that have changed from 1 to 0 are marked in red, while the bits that are among the selected N bits but have not changed because they were already set to 0 are marked in green. All possible variations that do not alter the instruction are ignored.<\/p>\n<p>Let&#8217;s see, for example, what can happen to the instruction <code>addi a6, a6, 0x1;<\/code> in different scenarios assuming a variation from 1 to 4 bits.<\/p>\n<p><strong>Red bits are the ones changed<\/strong>, <strong>green bits are the ones that should been changed but already were set to 0<\/strong>.<\/p>\n<p>The bit representation is consistent with that shown in the datasheet:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240121152043-1-2-1.png\" alt=\"Pasted image 20240121152043 1.png\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819215945-2-1.png\" alt=\"Pasted image 20240819215945.png\" \/><\/p>\n<p>Alternatively, a &#8220;reduced&#8221; version that does not include duplicate cases:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819222851-2-1.png\" alt=\"Pasted image 20240819222851.png\" \/><\/p>\n<p>The code can be viewed at <a href=\"https:\/\/github.com\/inode-\/fault_injection\/blob\/main\/OpcodeCalculator\/opcode_calculator.py\">https:\/\/github.com\/inode-\/fault_injection\/blob\/main\/OpcodeCalculator\/opcode_calculator.py<\/a><\/p>\n<h3>A better interpretation of the results<\/h3>\n<p>Now let&#8217;s try to understand what actually happens at the processor level, <strong>assuming that &#8220;the instruction was skipped&#8221; is not a valid answer<\/strong>.<\/p>\n<p>We start with the simplest cases and move towards the more complex and less &#8220;explainable&#8221; ones.<\/p>\n<p>The results from a normal execution are as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\"addi a6, a6, 0x1;\"  -&gt; a6 = 0x01 \r\n\"addi a6, a6, 0x2;\"  -&gt; a6 = 0x03 \r\n\"addi a6, a6, 0x4;\"  -&gt; a6 = 0x07 \r\n\"addi a6, a6, 0x8;\"  -&gt; a6 = 0x0F \r\n\"addi a6, a6, 0x10\"  -&gt; a6 = 0x1F \r\n\"addi a4, a6, 0x20\"  -&gt; a6 = 0x3F\r\n\"addi a6, a6, 0x40;\" -&gt; a6 = 0x7F\r\n<\/pre>\n<p>During the next steps, it is necessary to remember what the states of the registers are in a &#8220;normal&#8221; situation.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Core  0 register dump:\r\nPC      : 0x400d713b  PS      : 0x00060430  A0      : 0x40404040  A1      : 0x3ffb4810  \r\nA2      : 0x42424242  A3      : 0x43434343  A4      : 0x44444444  A5      : 0x45454545  \r\nA6      : 0x0000007f  A7      : 0x47474747  A8      : 0x48484848  A9      : 0x49494949  \r\nA10     : 0x50505050  A11     : 0x04000000  A12     : 0x3ff4400c  A13     : 0x93939393  \r\nA14     : 0x54545454  A15     : 0x55555555  SAR     : 0x00000004  EXCCAUSE: 0x0000001d  \r\nEXCVADDR: 0x93939393  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  \r\n<\/pre>\n<p>Some typical examples are analyzed below. <em>We have arbitrarily decided to consider that the maximum number of bits changed is 6, but the value could also be higher.<\/em><\/p>\n<h4>Level 1 (simple)<\/h4>\n<p>Difference between the normal registers:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">StoreProhibited - PC: 0x400d713b - A6 : 0x00000077(0x0000007f)  - \r\n<\/pre>\n<p>Which means:<\/p>\n<ul>\n<li>Expected value on A6 is 0x7F, we got 0x77 which means we have a difference of 0x8.<\/li>\n<li>Having a difference of 0x8 means that we faulted the 4th target instruction.<\/li>\n<li>No other registers have been affected.<\/li>\n<li>Calculating possible fault generated instructions, we can identify only one instruction which doesn&#8217;t generate a different CPU exception and causes the result to &#8220;add nothing&#8221;.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819223606-2-1.png\" alt=\"Pasted image 20240819223606.png\" \/><\/p>\n<p>That will produce:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\"addi a6, a6, 0x1;\"  -&gt; a6 = 0x01 \r\n\"addi a6, a6, 0x2;\"  -&gt; a6 = 0x03 \r\n\"addi a6, a6, 0x4;\"  -&gt; a6 = 0x07 \r\n\"addi a6, a6, 0x0;\"  -&gt; a6 = 0x07 | GLITCHED\r\n\"addi a6, a6, 0x10\"  -&gt; a6 = 0x17 \r\n\"addi a6, a6, 0x20\"  -&gt; a6 = 0x37\r\n\"addi a6, a6, 0x40;\" -&gt; a6 = 0x77\r\n<\/pre>\n<h4>Level 2 (simple)<\/h4>\n<p>Difference between the normal registers:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">StoreProhibited - PC: 0x400d713b - A4 : 0x0000003f(0x44444444)  - A6 : 0x0000005f(0x0000007f)  - \r\n<\/pre>\n<p>Which meanss:<\/p>\n<ul>\n<li>Expected value on A6 is 0x7F, we got 0x5f which means we have a difference of 0x20.<\/li>\n<li>Having a difference of 0x20 means that we faulted the 6th target instruction.<\/li>\n<li>Only register A4 has been changed, which means that in some way we have overwritten it.<\/li>\n<li>Calculating possible fault generated instructions, we can identify only one instruction which doesn&#8217;t generate a different CPU exception and causes the override of A4.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819223825-2-1.png\" alt=\"Pasted image 20240819223825.png\" \/><\/p>\n<p>That will produce:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\"addi a6, a6, 0x1;\"  -&gt; a6 = 0x01 \r\n\"addi a6, a6, 0x2;\"  -&gt; a6 = 0x03 \r\n\"addi a6, a6, 0x4;\"  -&gt; a6 = 0x07 \r\n\"addi a6, a6, 0x8;\"  -&gt; a6 = 0x0F \r\n\"addi a6, a6, 0x10\"  -&gt; a6 = 0x1F \r\n\"addi a4, a6, 0x20\"  -&gt; a6 = 0x1F, a4 = 0x3F | GLITCHED\r\n\"addi a6, a6, 0x40;\" -&gt; a6 = 0x5F, a4 = 0x3F\r\n<\/pre>\n<h4>Level 3 (simple)<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">StoreProhibited - PC: 0x400d713b - A2 : 0x40404041(0x42424242)  - A6 : 0x0000007e(0x0000007f)  - \r\n<\/pre>\n<p>Which means:<\/p>\n<ul>\n<li>Expected value on A6 is 0x7F, we got 0x7e which means we have a difference of 0x1.<\/li>\n<li>Having a difference of 0x1 means that we faulted the 1st target instruction.<\/li>\n<li>Register A2 contains the value of A0 plus one, which means that we changed both source and destination register in a single fault.<\/li>\n<li>Calculating possible fault generated instructions, we can identify only one instruction which doesn&#8217;t generate a different CPU exception and causes the override of A2 using A0 as source.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819223946-2-1.png\" alt=\"Pasted image 20240819223946.png\" \/><\/p>\n<p>That will produce:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\"addi a6, a6, 0x1;\"  -&gt; a6 = 0x00, a2 = 0x40404041 | GLITCHED\r\n\"addi a6, a6, 0x2;\"  -&gt; a6 = 0x02, a2 = 0x40404041\r\n\"addi a4, a6, 0x4;\"  -&gt; a6 = 0x06, a2 = 0x40404041\r\n\"addi a6, a6, 0x8;\"  -&gt; a6 = 0x0E, a2 = 0x40404041\r\n\"addi a6, a6, 0x10\"  -&gt; a6 = 0x1E, a2 = 0x40404041\r\n\"addi a6, a6, 0x20\"  -&gt; a6 = 0x3E, a2 = 0x40404041\r\n\"addi a6, a6, 0x40;\" -&gt; a6 = 0x7E, a2 = 0x40404041\r\n<\/pre>\n<h4>Level 4 (simple)<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">StoreProhibited - PC: 0x400d713b - A4 : 0x00000007(0x44444444)  - A6 : 0x0000007b(0x0000007f)  - \r\n<\/pre>\n<p>Which means:<\/p>\n<ul>\n<li>Expected value on A6 is 0x7F, we got 0x7b which means we have a difference of 0x4.<\/li>\n<li>Having a difference of 0x4 means that we faulted the 3rd target instruction.<\/li>\n<li>Only register A4 has been changed, which means that in some way we have overwritten it.<\/li>\n<li>Calculating possible fault generated instructions, we can identify only one instruction which doesn&#8217;t generate a different CPU exception and causes the override of A4.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819224040-2-1.png\" alt=\"Pasted image 20240819224040.png\" \/><\/p>\n<p>That will produce:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\"addi a6, a6, 0x1;\"  -&gt; a6 = 0x01 \r\n\"addi a6, a6, 0x2;\"  -&gt; a6 = 0x03 \r\n\"addi a4, a6, 0x4;\"  -&gt; a6 = 0x03, a4 = 0x7 | GLITCHED\r\n\"addi a6, a6, 0x8;\"  -&gt; a6 = 0x0B, a4 = 0x7 \r\n\"addi a6, a6, 0x10\"  -&gt; a6 = 0x1B, a4 = 0x7  \r\n\"addi a6, a6, 0x20\"  -&gt; a6 = 0x3B, a4 = 0x7  \r\n\"addi a6, a6, 0x40;\" -&gt; a6 = 0x7B, a4 = 0x7  \r\n<\/pre>\n<h4>Level 5 (medium)<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">StoreProhibited - PC: 0x400d713b - A0 : 0x0000001f(0x40404040)  - A4 : 0x0000002f(0x44444444)  - A6 : 0x0000004f(0x0000007f)  - \r\n<\/pre>\n<p>Which means:<\/p>\n<ul>\n<li>Expected value on A6 is 0x7F, we got 0x4f which means we have a difference of 0x30.<\/li>\n<li>Having a difference of 0x30 means that we faulted 2 target instructions, the 6th and the 7th.<\/li>\n<li>The A0 register contains the exact result of the standard 6th instruction.<\/li>\n<li>The A4 register contains a fault compatible with &#8220;the skip&#8221; of the 6th instruction and the sum generated from the 7th instruction.<\/li>\n<li>Calculating possible fault generated instructions, we can identify only one instruction which doesn&#8217;t generate a different CPU exception and causes the override of A0 and A4 in the correct way.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819224413-2-1.png\" alt=\"Pasted image 20240819224413.png\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819224620-2-1.png\" alt=\"Pasted image 20240819224620.png\" \/><\/p>\n<p>That will produce:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\"addi a6, a6, 0x1;\"  -&gt; a6 = 0x01 \r\n\"addi a6, a6, 0x2;\"  -&gt; a6 = 0x03 \r\n\"addi a6, a6, 0x4;\"  -&gt; a6 = 0x07 \r\n\"addi a6, a6, 0x8;\"  -&gt; a6 = 0x0F \r\n\"addi a0, a6, 0x10\"  -&gt; a6 = 0x0F, a0 = 0x1F             | GLITCHED\r\n\"addi a4, a6, 0x20\"  -&gt; a6 = 0x0F, a0 = 0x1F, a4 = 0x2F  | GLITCHED\r\n\"addi a6, a6, 0x40;\" -&gt; a6 = 0x7F\r\n<\/pre>\n<h4>Level 6 (medium)<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">StoreProhibited - PC: 0x400d713b - A4 : 0x00000005(0x44444444)  - A6 : 0x00000079(0x0000007f)  - \r\n<\/pre>\n<p>Which means:<\/p>\n<ul>\n<li>Expected value on A6 is 0x7F, we got 0x79 which means we have a difference of 0x6.<\/li>\n<li>Having a difference of 0x6 means that we faulted 2 target instructions, the 2nd and the 3rd.<\/li>\n<li>The A4 register contains a value that is compatible if the second instruction has not modified A6.<\/li>\n<li>Calculating possible fault generated instructions, we can identify only two instructions which don&#8217;t generate a different CPU exception and cause the override of A4 in the correct way.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819224835-2-1.png\" alt=\"Pasted image 20240819224835.png\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819224922-2-1.png\" alt=\"Pasted image 20240819224922.png\" \/><\/p>\n<p>That will produce:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\"addi a6, a6, 0x1;\"  -&gt; a6 = 0x01 \r\n\"addi a6, a6, 0x0;\"  -&gt; a6 = 0x01              | GLITCHED\r\n\"addi a4, a6, 0x4;\"  -&gt; a6 = 0x01, a4 =  0x5   | GLITCHED\r\n\"addi a6, a6, 0x8;\"  -&gt; a6 = 0x09, a4 =  0x5 \r\n\"addi a6, a6, 0x10\"  -&gt; a6 = 0x19, a4 =  0x5 \r\n\"addi a4, a6, 0x20\"  -&gt; a6 = 0x39, a4 =  0x5\r\n\"addi a6, a6, 0x40;\" -&gt; a6 = 0x79, a4 =  0x5\r\n<\/pre>\n<h4>Level 7 (medium)<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">StoreProhibited - PC: 0x400d713b - A6 : 0x42424262(0x0000007f)  - \r\n<\/pre>\n<p>Which means:<\/p>\n<ul>\n<li>The A6 register has been modified with the content of A2 (0x42424242).<\/li>\n<li>Difference between A2 and final A6 is 0x42424262 &#8211; 0x42424242 which is 0x20 meaning that we faulted the 6th target instruction.<\/li>\n<li>Register A6 is missing 0x40 which is the add of the last target instruction, so we corrupted 2 instructions.<\/li>\n<li>Calculating possible fault generated instructions, we can identify only one instruction which doesn&#8217;t generate a different CPU exception and causes the override of A6 with A2 value (6th instruction).<\/li>\n<li>Calculating possible fault generated instructions, we can identify one instruction which potentially doesn&#8217;t generate a different CPU exception and does nothing on A6.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819225348-2-1.png\" alt=\"Pasted image 20240819225348.png\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2024\/11\/Pasted-image-20240819225320-2-1.png\" alt=\"Pasted image 20240819225320.png\" \/><\/p>\n<p>That will produce:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">\"addi a6, a6, 0x1;\"  -&gt; a6 = 0x01 \r\n\"addi a6, a6, 0x2;\"  -&gt; a6 = 0x03 \r\n\"addi a6, a6, 0x4;\"  -&gt; a6 = 0x07 \r\n\"addi a6, a6, 0x8;\"  -&gt; a6 = 0x0F \r\n\"addi a6, a6, 0x10\"  -&gt; a6 = 0x1F \r\n\"addi a6, a2, 0x20\"  -&gt; a6 = 0x42424262 | GLITCHED\r\n\"addi a6, a6, 0x00\"  -&gt; a6 = 0x42424262 | GLITCHED\r\n<\/pre>\n<h3>Interpretation of the results &#8211; another approach<\/h3>\n<p>Comparing the possible instructions on which we have made a fault is possible in simple cases. However, in more complex scenarios it becomes difficult to manually explain the cases. For this reason, I have decided to also take another path, to emulate the execution of the fault in a virtual environment and subsequently compare the result. My first choice would have been to use <a href=\"https:\/\/www.unicorn-engine.org\/\">Unicorn Engine<\/a>, but unfortunately it does not currently support the XTENSA CPU.<\/p>\n<p>Another feasible approach could have been to use the JTAG port combined with GDB to modify the instructions and the context, to execute the instructions step by step and see what had changed. Technically feasible but probably too slow to perform as many emulations as we need.<\/p>\n<p>We then decided to try the emulation feature of Ghidra, which is poorly documented but should be supported for all CPUs. In fact, unlike for example IDA Pro, practically all processors come with what is defined as &#8220;P-Code&#8221;, that is, what a certain assembler operation performs. The P-Code abstraction is also what allows Ghidra to perform decompilation on almost all supported processors.<\/p>\n<h4>Ghidra CPU emulation<\/h4>\n<p>Some examples of using Ghidra for instruction emulation that I&#8217;ve used as a starting point:<\/p>\n<ul>\n<li><a href=\"https:\/\/gist.github.com\/cetfor\/18cae544249e4cf78f66930175072876\">https:\/\/gist.github.com\/cetfor\/18cae544249e4cf78f66930175072876<\/a><\/li>\n<li><a href=\"https:\/\/medium.com\/@cetfor\/emulating-ghidras-pcode-why-how-dd736d22dfb\">https:\/\/medium.com\/@cetfor\/emulating-ghidras-pcode-why-how-dd736d22dfb<\/a><\/li>\n<\/ul>\n<p>Reusing part of the Python code presented earlier, I decided to export the possible instructions that could be executed and import them directly into the code of our plugin.<\/p>\n<p>At this point, as a first step, we must modify the binary to reflect the instructions we want to emulate:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">void patch_code(long newcode[]) throws CancelledException, MemoryAccessException\r\n{\r\n\tAddress current_instruction = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(init_addr);\r\n\r\n\tfor(int i = 0; i &lt; newcode.length; i++) \r\n\t{\r\n\t\tclearListing(current_instruction);\r\n\r\n\t\tthis.setBytes(current_instruction, longToBytes_24bits(newcode[i]));\t\t\r\n\t\tcurrent_instruction = current_instruction.add(3);\t\t\r\n\t}\r\n\t\r\n\tdisassemble(currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(init_addr));\t\t\r\n\treturn;\r\n\r\n}\r\n<\/pre>\n<p>Then we set the context exactly as what is expected by the CPU:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">emuHelper.writeRegister(\"a0\", 0x40404040);\r\nemuHelper.writeRegister(\"a1\", 0x41414141);\r\nemuHelper.writeRegister(\"a2\", 0x42424242);\r\nemuHelper.writeRegister(\"a3\", 0x43434343);\r\nemuHelper.writeRegister(\"a4\", 0x44444444);\r\nemuHelper.writeRegister(\"a5\", 0x45454545);\r\nemuHelper.writeRegister(\"a6\", 0x46464646);\r\nemuHelper.writeRegister(\"a7\", 0x47474747);\r\nemuHelper.writeRegister(\"a8\", 0x48484848);\r\nemuHelper.writeRegister(\"a9\", 0x49494949);\r\nemuHelper.writeRegister(\"a10\", 0x50505050);\r\nemuHelper.writeRegister(\"a11\", 0x51515151);\r\nemuHelper.writeRegister(\"a12\", 0x52525252);\r\nemuHelper.writeRegister(\"a13\", 0x93939393);\r\nemuHelper.writeRegister(\"a14\", 0x54545454);\r\nemuHelper.writeRegister(\"a15\", 0x55555555);\r\n\r\nemuHelper.writeRegister(\"a6\", 0x0);\r\n<\/pre>\n<p>Afterwards, we execute the instructions of interest:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">\temuHelper.writeRegister(emuHelper.getPCRegister(), initial_instruction);\r\n\t\r\n\tint j = 0;\r\n\t\r\n\tfor(int i = 0; i&lt;=array_size; i++)\r\n\t{\r\n\t\tAddress executionAddress = emuHelper.getExecutionAddress();\r\n\t\t\r\n\t\toutfile.write(executionAddress.toString() + ' ' + getInstructionAt(executionAddress) + \"\\n\");\r\n\t\t\r\n\t\ttry {\r\n\t\t\tboolean success = emuHelper.step(monitor);\r\n\t\t\t\r\n\t\t\tj++;\r\n\t\t\tif( success == false) {\r\n\t\t\t\tString lastError = emuHelper.getLastError();\r\n\t\t\t\toutfile.write(lastError  + \" - \" +  getInstructionAt(executionAddress) + \"\\n\");\r\n\t\t\t\toutfile.write(HexFormat.of().formatHex(getBytes(executionAddress, 3)));\r\n\t\t\t\treturn -1;\r\n\t\t\t}\r\n\t\t} catch (Exception e) {\r\n\t\t\tprintln(e.toString());\r\n\t\t\treturn -1;\r\n\t\t\t\r\n\t\t}\r\n\t\t\r\n\t}\r\n<\/pre>\n<p>At this point, we compare the results and save only those that are different from what we expect:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">\t\tif(emuHelper.readRegister(\"a0\").longValue() != 0x40404040 )\r\n\t\t\toutfile.write(\"A0 : 0x\" + String.format(\"%08x\", emuHelper.readRegister(\"a0\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a1\").longValue() != 0x41414141 )\r\n\t\t\toutfile.write(\"A1 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a1\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a2\").longValue() != 0x42424242 )\r\n\t\t\toutfile.write(\"A2 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a2\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a3\").longValue() != 0x43434343 )\r\n\t\t\toutfile.write(\"A3 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a3\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a4\").longValue() != 0x44444444 )\r\n\t\t\toutfile.write(\"A4 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a4\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a5\").longValue() != 0x45454545 )\r\n\t\t\toutfile.write(\"A5 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a5\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a6\").longValue() != 0x7f )\r\n\t\t\toutfile.write(\"A6 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a6\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a7\").longValue() != 0x47474747 )\r\n\t\t\toutfile.write(\"A7 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a7\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a8\").longValue() != 0x48484848 )\r\n\t\t\toutfile.write(\"A8 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a8\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a9\").longValue() != 0x49494949 )\r\n\t\t\toutfile.write(\"A9 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a9\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a10\").longValue() != 0x50505050 )\r\n\t\t\toutfile.write(\"A10 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a10\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a11\").longValue() != 0x51515151 )\r\n\t\t\toutfile.write(\"A11 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a11\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a12\").longValue() != 0x52525252 )\r\n\t\t\toutfile.write(\"A12 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a12\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a13\").longValue() != 0x93939393L )\r\n\t\t\toutfile.write(\"A13 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a13\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a14\").longValue() != 0x54545454 )\r\n\t\t\toutfile.write(\"A14 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a14\").longValue()) + \" \");\r\n\t\tif(emuHelper.readRegister(\"a15\").longValue() != 0x55555555 )\r\n\t\t\toutfile.write(\"A15 : 0x\" + String.format(\"%08x\",emuHelper.readRegister(\"a15\").longValue()) + \" \");\r\n\t\toutfile.write(HexFormat.of().formatHex(getBytes(currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(init_addr), 3*7)));\r\n\t\toutfile.write(\"\\n\");\r\n\t\t\r\n<\/pre>\n<p>Full code available at<a href=\"https:\/\/github.com\/inode-\/fault_injection\/blob\/main\/GhidraEmulation\/xtensa_emulator.java\"> https:\/\/github.com\/inode-\/fault_injection\/blob\/main\/GhidraEmulation\/xtensa_emulator.java<\/a><\/p>\n<h4>Pros and cons<\/h4>\n<p>One of the main pros of this approach is the possibility of having an emulator up and running in a very short time, even though Ghidra&#8217;s APIs are poorly documented. However, there are also a number of cons:<\/p>\n<ul>\n<li>the procedure to emulate everything is slow<\/li>\n<li>we cannot be certain that some exceptions are handled in the same way by the emulation layer as by the original hardware<\/li>\n<\/ul>\n<h3>Conclusions<\/h3>\n<p>One thing <strong>we can state with certainty is that instructions are not &#8220;skipped&#8221;&#8230;<\/strong><\/p>\n<p>Sometimes it is not easy to explain what happens in the context of fault injection, but it is possible to try to <strong>understand what happened if there is a clear context<\/strong>. Of course, <strong>we cannot be certain, but we can come to have a good degree of confidence<\/strong> in understanding what happened in some cases. In the next articles in this <a href=\"https:\/\/hnsecurity.it\/tag\/fault-injection\">series<\/a>, I will try to find other ways to interpret the results.<\/p>\n<p>Another important finding is that somehow <strong>it is possible to affect multiple instructions<\/strong>, and the modified bits don&#8217;t have to be contiguous.<\/p>\n<p>Certainly, this article does not intend to be exhaustive, and I know there are many opportunities for improvement. For example, in the context we are working on, the floating-point registers are not printed, but as a start, I would dare to say that it is more than enough.<\/p>\n<p><em>Once again, I&#8217;d like to thank <a href=\"https:\/\/twitter.com\/tieknimmers\">@tieknimmers<\/a> and <a href=\"https:\/\/twitter.com\/pulsoid\">@pulsoid<\/a> for their invaluable support during the writing of this article and for putting up with my endless questions and queries.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Intro This series of articles describes fault injection attack techniques in order to understand their real potential by testing their [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":159901,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[91],"tags":[149,217,73,77,87,147],"class_list":["post-4682","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-articles","tag-iot","tag-fault-injection","tag-research","tag-exploit","tag-reverse-engineering","tag-hardware"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>HN Security Fault Injection - Down the Rabbit Hole<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HN Security Fault Injection - Down the Rabbit Hole\" \/>\n<meta property=\"og:description\" content=\"Intro This series of articles describes fault injection attack techniques in order to understand their real potential by testing their [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/\" \/>\n<meta property=\"og:site_name\" content=\"HN Security\" \/>\n<meta property=\"article:published_time\" content=\"2024-11-13T09:10:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-09-11T07:20:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/CIRCUITI.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"836\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Maurizio Agazzini\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@hnsec\" \/>\n<meta name=\"twitter:site\" content=\"@hnsec\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Maurizio Agazzini\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"28 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/\"},\"author\":{\"name\":\"Maurizio Agazzini\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/person\\\/d667b46361c97bc294ea383b8f6de9b3\"},\"headline\":\"Fault Injection &#8211; Down the Rabbit Hole\",\"datePublished\":\"2024-11-13T09:10:51+00:00\",\"dateModified\":\"2025-09-11T07:20:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/\"},\"wordCount\":4441,\"publisher\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/CIRCUITI.jpg\",\"keywords\":[\"iot\",\"fault injection\",\"research\",\"exploit\",\"reverse engineering\",\"hardware\"],\"articleSection\":[\"Articles\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/\",\"name\":\"HN Security Fault Injection - Down the Rabbit Hole\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/CIRCUITI.jpg\",\"datePublished\":\"2024-11-13T09:10:51+00:00\",\"dateModified\":\"2025-09-11T07:20:27+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/#primaryimage\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/CIRCUITI.jpg\",\"contentUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/CIRCUITI.jpg\",\"width\":1600,\"height\":836},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/fault-injection-down-the-rabbit-hole\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Fault Injection &#8211; Down the Rabbit Hole\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#website\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/\",\"name\":\"HN Security\",\"description\":\"Offensive Security Specialists\",\"publisher\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#organization\",\"name\":\"HN Security\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/hn-libellula.jpg\",\"contentUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/hn-libellula.jpg\",\"width\":696,\"height\":696,\"caption\":\"HN Security\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/hnsec\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/hnsecurity\\\/\",\"https:\\\/\\\/github.com\\\/hnsecurity\",\"https:\\\/\\\/infosec.exchange\\\/@hnsec\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/person\\\/d667b46361c97bc294ea383b8f6de9b3\",\"name\":\"Maurizio Agazzini\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fafe3b3da91f9b35c3ef9816ff3d2c24f8936f3fc1e683239d52e77b0942c101?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fafe3b3da91f9b35c3ef9816ff3d2c24f8936f3fc1e683239d52e77b0942c101?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/fafe3b3da91f9b35c3ef9816ff3d2c24f8936f3fc1e683239d52e77b0942c101?s=96&d=mm&r=g\",\"caption\":\"Maurizio Agazzini\"},\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/author\\\/maurizio-agazzini\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HN Security Fault Injection - Down the Rabbit Hole","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/","og_locale":"it_IT","og_type":"article","og_title":"HN Security Fault Injection - Down the Rabbit Hole","og_description":"Intro This series of articles describes fault injection attack techniques in order to understand their real potential by testing their [&hellip;]","og_url":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/","og_site_name":"HN Security","article_published_time":"2024-11-13T09:10:51+00:00","article_modified_time":"2025-09-11T07:20:27+00:00","og_image":[{"width":1600,"height":836,"url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/CIRCUITI.jpg","type":"image\/jpeg"}],"author":"Maurizio Agazzini","twitter_card":"summary_large_image","twitter_creator":"@hnsec","twitter_site":"@hnsec","twitter_misc":{"Scritto da":"Maurizio Agazzini","Tempo di lettura stimato":"28 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/#article","isPartOf":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/"},"author":{"name":"Maurizio Agazzini","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/d667b46361c97bc294ea383b8f6de9b3"},"headline":"Fault Injection &#8211; Down the Rabbit Hole","datePublished":"2024-11-13T09:10:51+00:00","dateModified":"2025-09-11T07:20:27+00:00","mainEntityOfPage":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/"},"wordCount":4441,"publisher":{"@id":"https:\/\/hnsecurity.it\/it\/#organization"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/#primaryimage"},"thumbnailUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/CIRCUITI.jpg","keywords":["iot","fault injection","research","exploit","reverse engineering","hardware"],"articleSection":["Articles"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/","url":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/","name":"HN Security Fault Injection - Down the Rabbit Hole","isPartOf":{"@id":"https:\/\/hnsecurity.it\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/#primaryimage"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/#primaryimage"},"thumbnailUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/CIRCUITI.jpg","datePublished":"2024-11-13T09:10:51+00:00","dateModified":"2025-09-11T07:20:27+00:00","breadcrumb":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/#primaryimage","url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/CIRCUITI.jpg","contentUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/CIRCUITI.jpg","width":1600,"height":836},{"@type":"BreadcrumbList","@id":"https:\/\/hnsecurity.it\/it\/blog\/fault-injection-down-the-rabbit-hole\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/hnsecurity.it\/it\/"},{"@type":"ListItem","position":2,"name":"Fault Injection &#8211; Down the Rabbit Hole"}]},{"@type":"WebSite","@id":"https:\/\/hnsecurity.it\/it\/#website","url":"https:\/\/hnsecurity.it\/it\/","name":"HN Security","description":"Offensive Security Specialists","publisher":{"@id":"https:\/\/hnsecurity.it\/it\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hnsecurity.it\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Organization","@id":"https:\/\/hnsecurity.it\/it\/#organization","name":"HN Security","url":"https:\/\/hnsecurity.it\/it\/","logo":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/","url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg","contentUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg","width":696,"height":696,"caption":"HN Security"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/hnsec","https:\/\/www.linkedin.com\/company\/hnsecurity\/","https:\/\/github.com\/hnsecurity","https:\/\/infosec.exchange\/@hnsec"]},{"@type":"Person","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/d667b46361c97bc294ea383b8f6de9b3","name":"Maurizio Agazzini","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/fafe3b3da91f9b35c3ef9816ff3d2c24f8936f3fc1e683239d52e77b0942c101?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/fafe3b3da91f9b35c3ef9816ff3d2c24f8936f3fc1e683239d52e77b0942c101?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/fafe3b3da91f9b35c3ef9816ff3d2c24f8936f3fc1e683239d52e77b0942c101?s=96&d=mm&r=g","caption":"Maurizio Agazzini"},"url":"https:\/\/hnsecurity.it\/it\/blog\/author\/maurizio-agazzini\/"}]}},"jetpack_featured_media_url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/CIRCUITI.jpg","_links":{"self":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/4682","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/comments?post=4682"}],"version-history":[{"count":1,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/4682\/revisions"}],"predecessor-version":[{"id":160083,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/4682\/revisions\/160083"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media\/159901"}],"wp:attachment":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media?parent=4682"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/categories?post=4682"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/tags?post=4682"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}