Utilisation d'une plateforme d'attaque et d'analyse (TP)

In this tutorial, we are introducing the ChipWhisperer-Lite boards. Parts of the information on this site are taken from the official Wiki of NewAE. For more tutorials, for troubleshooting and help, please visit the Wiki here: https://wiki.newae.com/CW1173_ChipWhisperer-Lite

1. Getting Started

1.1 Hardware

This is how the ChipWhisperer-Lite board looks like:

The main board on the left contains everything needed to perform measurements (ADC...), to mount glitching attacks and to communicate with the host PC. The target board on the right contains an ATMEL XMEGA microcontroller, which can be programmed with any software that you want to attack and analyse.


1.2 Software

Open a terminal and go to your home directory. Type in or copy and paste the following commands:

cd ~
wget https://perso.telecom-paristech.fr/ukuhne/cwtut/cwtut.tgz
tar xzf cwtut.tgz
echo 'export PATH=/comelec/softs/bin/:$PATH' >> .zshrc
echo 'export PYTHONPATH=/comelec/softs/opt/chipwhisperer/install/lib/python2.7/site-packages:$PYTHONPATH' >> .zshrc
source .zshrc
ls /comelec/softs > /dev/null

To start the analysis tool, execute the following command:

chipwhisperer-cap

This should fire up the gui of the ChipWhisperer platform:

For this tutorial, the most important controls are the settings dialog on the left hand side, as well as the power trace view on the right hand side.


2. Simple Power Analysis

2.1 Viewing the Power Profile of Different Instructions

In this first simple exercise, we want to inspect the power traces induced by different instructions running on the XMEGA target. For this purpose, we have prepared a dummy program that can be loaded onto the XMEGA. Open a terminal and go to the directory containing the source code:

$> cd ~/cwtut/firmware/basic-instructions

Have a look into the source file basic-instructions.c. Locate the following lines in the code:

    trigger_high();
   
    asm volatile(
             "nop"       "\n\t"
             "nop"       "\n\t"
             "nop"       "\n\t"
             "nop"       "\n\t"
             "nop"       "\n\t"
             "nop"       "\n\t"
             "nop"       "\n\t"
             "nop"       "\n\t"
             "nop"       "\n\t"
             "nop"       "\n\t"
             ::
             );

    asm volatile(
             "mul r0,r1" "\n\t"
             "mul r0,r1" "\n\t"
             "mul r0,r1" "\n\t"
             "mul r0,r1" "\n\t"
             "mul r0,r1" "\n\t"
             "mul r0,r1" "\n\t"
             "mul r0,r1" "\n\t"
             "mul r0,r1" "\n\t"          
             "mul r0,r1" "\n\t"
             "mul r0,r1" "\n\t"
             ::
             );
   
    trigger_low();
  • What does this program do?
  • Can you guess the purpose of the trigger_high() and trigger_low() function calls?

In order to load this program on the target board, we need to compile it first. Go back to the terminal and type in the following command:

make

If everything goes fine, there should now be a file basic-instructions-CW303.hex in the current directory. It contains the binary code that we can now use to program the XMEGA. Next, switch to the ChipWhisperer gui.

Instead of setting up all the parameters by hand, it is a good idea to start with one of the example scripts that come with the software. For this tutorial, since we use the simple serial interface, we choose the script named 'ChipWhisperer Lite: SPA SimpleSerial on XMEGA', which can be found in the menu Project -> Example Scripts.

Once the script starts executing, there are a lot of things happening in the gui. Most notably, you should see the indicator buttons for the connections to the board going green like this:

If this is not the case, there is a problem with the connection to your board. Check the USB cable, udev rules and user rights!

Next, fire up the programmmer tool, which can be found in the menu Tools -> CW Lite XMEGA Programmer. Find the .hex file that you just compiled and push the Erase/Program/Verify Flash button. The result should look roughly like this:

Now we are ready to go to take some measurements and inspect the power traces. Push the Capture 1 button a few times to refresh the power trace view:

If needed, you can adjust the oscilloscope setttings. Go to the Scope Settings tab:

  • In the section OpenADC -> Gain Settings, play with the gain settings until you have a good signal.
  • Go to the section OpenADC -> Trigger Setup and set the number of Total Samples to 500

Now look at the power trace.

  • Can you figure out which part of the trace corresponds to the inline assembler in the source code?
  • Can you identify the NOP and the MUL instructions?
  • Try changing the source code (adding more NOP, duplicating the whole sequence, ...) and observe the effects on the power trace. Note that you need to recompile and reprogram after each change.

2.2 Cracking a PIN

2.2.1 Compiling the source code

We will now use a Simple Power Analysis (SPA) attack in order to find a secret PIN number. Go to the directory ~/chipwhisperer/hardware/victims/firmware/basic-pin and inspect the source code in basic-pin.c. The interesting things happen in this part of the source code:

  char correct_pin[] = "1234";
[...]
    //Get pin
    printf("Please enter PIN to continue: ");
    scanf("%s", pin);
       
    uint8_t passbad = 0;
       
    trigger_high();
       
    for(uint8_t i = 0; i < sizeof(correct_pin); i++){
      if (correct_pin[i] != pin[i]){
        passbad = 1;
        break;
      }
    }
[...]
  • What is the security problem with the PIN check code in the for loop?
  • How can we take advantage of this using SPA?

Of course the PIN is just there in plain text in the source code, but we assume that the binary code for a specific device contains an unknown PIN and that we cannot access the binary code on the device. It is a valid attack scenario that we have access to one device for which we can manipulate voluntarily the PIN and test our attack before switching to the real target and using our knowledge to crack the unknown PIN.

First, compile the source code by typing in the command

make

and load the binary code (file basic-pin-CW303.hex) onto the XMEGA target using the XMEGA programmer tool.

2.2.2 First manual measurements

Later, when automating our attack, we will use a separate python script to communicate with the target. For now, we will connect to it manually. For this purpose, open a terminal (in the menu tools of the ChipWhisperer tool). When you hit the connect button, you should see the prompt message from the XMEGA, asking you to enter a PIN:

If you want to retry, you can reset the target manually by hitting the Check Signature button in the programmer interface. Next, we would like to capture a power trace while the target is checking the entered PIN number. Again, we can just hit the Capture 1 button to arm the scope. Measurement starts once the trigger signal goes high. One thing to adjust before doing so is the timeout, since we are sending the PIN manually for now:

  • Go to the Scope Settings tab
  • Go to the option OpenADC -> Trigger Setupt -> Timeout (secs)
  • Set the timeout to 5s or more

This will give us enough time to switch to the terminal and hitting enter to send the PIN after arming the scope.

  • Performe some measuerments, hitting the Capture 1 button and then quickly sending a PIN to the target
  • Change the PIN number (we know the good one is 1234)
  • Try prefixes with 1, 2, 3 correct digits and look at the changes in the power trace

The result should look more or less like this:

If you see strange things happen in the terminal (messages sent on hitting the capture button), perform the following steps:

  • Switch to the Target Settings tab
  • Set the Protocol Version to 1.0
  • Clear the entries in the fields Load Key Command, Go Command, and Output Format.

The above entries are actually used to automate the communication with the target devices. This includes setting encryption keys, sending clear text or configuration messages and parsing the device's response. For our purpose, we can make use of these features to avoid sending the PIN manually:

  • Switch to the Target Settings tab
  • Edit the field Go Command and enter 1234\n

Now, every time you hit the Capture 1 button, the tool automatically sends the string "1234" (followed by a newline) to the target.

2.2.3 Scripting the attack

In order to mount a real attack on the PIN check, we will write a dedicated script that will do all the work for us.

  • Go to the directory ~/cwtut/pincracker/pin, where you should find a code skeleton pincracker.py that has been prepared for this exercise.
  • Open the file in your favorite text editor and look at the code.
[...]  
    def crackPIN(self):
        digits = '0123456789'

        # This is how to change the PIN
        self.setPIN('9876')

        # This is how to get a trace
        self.api.capture1()
        data = self.api.getScope().channels[0].getTrace()

        # ============================
        # TODO: Fill in your code here
        # ============================
       
        goodPIN = '1234'
        return goodPIN
[...]
    def run(self):
[...]
        # Let's go!
        pin = self.crackPIN()
        self.setPIN(pin)
        print ("============================")
        print ("The PIN is %s" % pin)
        print ("============================")                             

If you run this script in a terminal:

python pincracker.py

the main() function of the PincrackerScript class will be executed. This in turn will call the function crackPIN(). This is where you should put your code in order to extract the correct PIN based on the power consumption measurements. In the code skeleton, you should have all the tools necessary for a successful attack. The trace returned from the scope is just a python list with floating point numbers, one float for each sample. Running the script will open a new instance of the ChipWhisperer gui. The output of print commands in your script appears in the Debug Logging tab in the gui.

Now write the attack script:

  • Extract the correct first digit of the PIN: Loop over the ten possible digits, set the PIN and get the power trace. Can you figure out which trace corresponds to the correct digit?

Basically, there is two ways to do this:

  1. Point of Interest (POI): Find a single point in the trace that helps distinguishing a good digit from a bad one. This involves a thorough manual inspection and some trial and error.
  2. Statistical evaluation: If there is no countermeasure such as randomisation, then all bad traces should look more or less the same. You can find the one good trace by comparing each trace with the average trace over all candidates.

The advantage of the POI method is that it will be faster once you figured out the right point. Also, you can stop the search once you found the right digit and proceed to the next one. The statistical method is more robust with respect to environmental noise and imprecise measurements, but needs more computation. Choose one of the two methods and figure out the first digit.

  • Now generalise your script in order to extract the whole (four digit) PIN

If you have chosen a point of interest, note that this point will probably shift in time when proceeding with the second, third, ... digit. Again, the statistical method is more robust but slower.

  • Test your script. In the same directory as the attack script, there is a file crackme.hex. Upload it to the target device and try to find the hidden PIN. Compare your result with your classmates.
  • If you used a POI, try a statistical method and vice versa

3. More Attacks

There are more things to do with the ChipWhisperer board. You can explore the tutorials on the Wiki if you like. You might want to consider the following exercises:

  1. Differential Power Analysis on AES
  2. Glitching attack to bypass a password check