Ready to write first attack

I am ready to write my first attack… Will try to update my code below as I progress. Appreciate ANY help.

  • Using Chipwhisperer LITE, 2 part kit
  • target chip (this will be the DUT).
  • have made a board that communicates with this chip over serial.
  • Use Lab 2_1B, power monitoring on password as skeleton code

Right after power up, the chip will wait for a password to be entered.
Password length is 8 characters, anything from 00 - FF.
Chip must be reset after every attempt (power off, wait a second, power on) try again.

My challenges

  • How to connect my DUT to the Chipwhisperer LITE for power monitoring and serial exchange?
  • Learning Python as I go…
  • How to power cycle the chip on every attempt? Is it cw.target(disconnect) and cw.target(scope, cw.targets.SimpleSerial) ?
  • What to use as a trigger? Don’t really need one, right?
  • Need to make the changes in the function “cap_pass_trace()” to power cycle, and enter 1 char only?
  • Set baud rate to 19,200…

My code so far -

SCOPETYPE = 'OPENADC'
PLATFORM  = 'CUSTOM'

import chipwhisperer as cw
import matplotlib.pyplot as plt

# Globals
# Characters to test, all 255 chars  (256?)
totest = { '\00', '\01', '\02', '\03', '\04', '\05', '\06', '\07', '\08', '\09', '\0a', '\0b', '\0c', '\0d', '\0e', '\0f', \
           '\10', '\11', '\12', '\13', '\14', '\15', '\16', '\17', '\18', '\19', '\1a', '\1b', '\1c', '\1d', '\1e', '\1f', \
           '\20', '\21', '\22', '\23', '\24', '\25', '\26', '\27', '\28', '\29', '\2a', '\2b', '\2c', '\2d', '\2e', '\2f', \
           '\30', '\31', '\32', '\33', '\34', '\35', '\36', '\37', '\38', '\39', '\3a', '\3b', '\3c', '\3d', '\3e', '\3f', \
           '\40', '\41', '\42', '\43', '\44', '\45', '\46', '\47', '\48', '\49', '\4a', '\4b', '\4c', '\4d', '\4e', '\4f', \
           '\50', '\51', '\52', '\53', '\54', '\55', '\56', '\57', '\58', '\59', '\5a', '\5b', '\5c', '\5d', '\5e', '\5f', \
           '\60', '\61', '\62', '\63', '\64', '\65', '\66', '\67', '\68', '\69', '\6a', '\6b', '\6c', '\6d', '\6e', '\6f', \
           '\70', '\71', '\72', '\73', '\74', '\75', '\76', '\77', '\78', '\79', '\7a', '\7b', '\7c', '\7d', '\7e', '\7f', \
           '\80', '\81', '\82', '\83', '\84', '\85', '\86', '\87', '\88', '\89', '\8a', '\8b', '\8c', '\8d', '\8e', '\8f', \
           '\90', '\91', '\92', '\93', '\94', '\95', '\96', '\97', '\98', '\99', '\9a', '\9b', '\9c', '\9d', '\9e', '\9f', \
           '\a0', '\a1', '\a2', '\a3', '\a4', '\a5', '\a6', '\a7', '\a8', '\a9', '\aa', '\ab', '\ac', '\ad', '\ae', '\af', \
           '\b0', '\b1', '\b2', '\b3', '\b4', '\b5', '\b6', '\b7', '\b8', '\b9', '\ba', '\bb', '\bc', '\bd', '\be', '\bf', \
           '\c0', '\c1', '\c2', '\c3', '\c4', '\c5', '\c6', '\c7', '\c8', '\c9', '\ca', '\cb', '\cc', '\cd', '\ce', '\cf', \
           '\d0', '\d1', '\d2', '\d3', '\d4', '\d5', '\d6', '\d7', '\d8', '\d9', '\da', '\db', '\dc', '\dd', '\de', '\df', \
           '\e0', '\e1', '\e2', '\e3', '\e4', '\e5', '\e6', '\e7', '\e8', '\e9', '\ea', '\eb', '\ec', '\1e', '\ee', '\ef', \
           '\f0', '\f1', '\f2', '\f3', '\f4', '\f5', '\f6', '\f7', '\f8', '\f9', '\fa', '\fb', '\fc', '\fd', '\fe', '\ff' }

try:
    if not scope.connectStatus:
        scope.con()
except NameError:
    scope = cw.scope()

try:
    if SS_VER == "SS_VER_2_0":
        target_type = cw.targets.SimpleSerial2
    else:
        target_type = cw.targets.SimpleSerial
except:
    SS_VER="SS_VER_1_1"
    target_type = cw.targets.SimpleSerial

try:
    target = cw.target(scope, target_type)
except IOError:
    print("INFO: Caught exception on reconnecting to target - attempting to reconnect to scope first.")
    print("INFO: This is a work-around when USB has died without Python knowing. Ignore errors above this line.")
    scope = cw.scope()
    target = cw.target(scope, target_type)

print("INFO: Found ChipWhisperer😍")
print(scope.get_serial_ports())

# Set scope defaults - Scope gain 45db, Scope capture 5000, Scope offset to 0, Sets scope trigger to rising edge
# 7.37mhz clock output on HS2, Clocks the scope ADC at 4*7.37MHz. Note that this is synchronous to the target 
# clock on HS2.  GPIO1 as RX, GPIO2 as TX
scope.default_setup()

# Lower sample rate to 500
scope.adc.samples = 500

# Define functions
def cap_pass_trace(pass_guess):
    reset_target(scope)
    num_char = target.in_waiting()
    while num_char > 0:
        target.read(num_char, 10)
        time.sleep(0.01)
        num_char = target.in_waiting()

    scope.arm()
    target.write(pass_guess)
    ret = scope.capture()
    if ret:
        print('Timeout happened during acquisition')

    trace = scope.get_last_trace()
    return trace


%matplotlib inline
plt.figure()
plt.plot(cap_pass_trace("h\n"))
plt.plot(cap_pass_trace("0\n"))
plt.show()


# Connect to TARGET
target = cw.target(scope, cw.targets.SimpleSerial) #cw.targets.SimpleSerial can be omitted


# Do the password test...
 for c in totest:
    trace = cap_pass_trace(c)[0:500]
    plt.plot(trace - ref_trace)

 trace = cap_pass_trace(guessed_pw + c)
 diff = np.sum(np.abs(trace - ref_trace))

 if diff > 40.0:
      guessed_pw += c
      print(guessed_pw)
      break

I think you’ve generally got the right idea here. Some feedback:

The steps are pretty similar to what’s done in this old lab: Tutorial A9 Bypassing LPC1114 Read Protect - ChipWhisperer Wiki. Basically, you need to:

  1. Insert a shunt resistor between the Vcc on the target board and the DUT
  2. Remove all decoupling capacitors on the low side of the shunt
  3. Connect the low side of the shunt to the measure port on the ChipWhisperer
  4. Make any other required electrical connections (serial, trigger, reset, etc.)

You can toggle power via scope.io.target_pwr (Deprecated API — ChipWhisperer 5.7.0 documentation). The SimpleSerial class that you use most of the time only deals with serial communication.

The trigger is actually one of the most important parts of setting up an attack. Otherwise, you’re going to be capturing random microsecond long traces with a few seconds of jitter.

Also, you can replace your totest with bytearray(range(256)). {} are used for the built-in dict type in Python. You want [] if you want to replicate C arrays

Alex