This commit is contained in:
2024-06-28 04:07:22 -06:00
parent e7bfcd1a78
commit 4da90cf9fe
7 changed files with 77 additions and 30 deletions
+1
View File
@@ -2,3 +2,4 @@
.micropico .micropico
PiPicoPATLFGGGGG.code-workspace PiPicoPATLFGGGGG.code-workspace
main_dev.py main_dev.py
ComicCode-Regular.*
+12
View File
@@ -0,0 +1,12 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
+17 -2
View File
@@ -4,7 +4,7 @@
A tool for simplifying power analysis attacks against other gadgets. A tool for simplifying power analysis attacks against other gadgets.
Built on the Raspberry Pi Pico W, it runs a PWM channel to do manual clock control on the nugget you're hacking, and then reads an ADC channel to measure voltage used at each clock cycle. Built on the Raspberry Pi Pico W, it runs a PWM channel to do manual clock control on the nugget you're hacking, and then reads an ADC channel to measure voltage used at each clock cycle.
## Installataion ## Installation
Make sure you have Micropython installed on your Pico W. Make sure you have Micropython installed on your Pico W.
Open up your Pico W in your favorite IDE (Thonny and VS Code are commonly used) and upload main.py. Open up your Pico W in your favorite IDE (Thonny and VS Code are commonly used) and upload main.py.
If you're having trouble, see the official [Raspberry Pi Pico W Getting Started Page](https://projects.raspberrypi.org/en/projects/get-started-pico-w) If you're having trouble, see the official [Raspberry Pi Pico W Getting Started Page](https://projects.raspberrypi.org/en/projects/get-started-pico-w)
@@ -74,4 +74,19 @@ For #2, we need to remove the builtin crystal oscilator and replace that connect
For this example, I will describe a firmware decryption power analysis attack. For this example, I will describe a firmware decryption power analysis attack.
Scenario: You have and ESP32-S3 based device with flash and bootloader encryption set up on it. You Can remove the RF sheield and get a raw dump of the flash chip with a SOP8 test clip and a programmer, but the data is encrypted. Scenario: You have and ESP32-S3 based device with flash and bootloader encryption set up on it. You Can remove the RF sheield and get a raw dump of the flash chip with a SOP8 test clip and a programmer, but the data is encrypted.
## Method
1) We disassemble the device to the bare board we're interested in
2) Then remove the RF shield and crystal oscilator from the ESP32-S3 via reflow
3) Clip a SOP8 test clip on the 8pin flash chip and dump the encrypted data with a programmer like a CH431a or T48
4) Set up the breadboard with the Pico W.
5) Place the clock_pulse_pin probe where the crystal oscillator used to be
6) Place power_analysis_pin probe on the rawest vin power spot you can find
7) Run the Pico W (see Usage)
8) Dump serial data to some manner of logger Todo: figure out this tooling
9) Perform statistical attack to dump key! Todo: automate and figure out tooling
Distributed under the [WTFPL - The Do What the Fuck You Want to Public License](http://www.wtfpl.net/)
See [COPYING.txt](COPYING.txt)
![WTFPL](resources/wtfpl.png)
+47 -28
View File
@@ -4,7 +4,7 @@ import machine
import utime import utime
import _thread import _thread
import math import math
import os #import os
# gpio pin to read power analysis off of (int) # gpio pin to read power analysis off of (int)
@@ -33,6 +33,7 @@ def do_pwm(outpin = 20, duty_cycle = 0.5, frequency = 2000):
pwm_pin.duty_u16(pwm_duty) pwm_pin.duty_u16(pwm_duty)
print(f"Clock Pulses Running\n\tGPIO Pin: {outpin}\n\tDuty Cycle: {percent_duty}%\n\tFrequency: {frequency}Hz") print(f"Clock Pulses Running\n\tGPIO Pin: {outpin}\n\tDuty Cycle: {percent_duty}%\n\tFrequency: {frequency}Hz")
# us of sleep calculate4d by floor(1000000 / (frequency_in_Hz * samples_per_pulse))
def us_samples(frequency, samples_per_pulse): def us_samples(frequency, samples_per_pulse):
return math.floor(1000000/(frequency*samples_per_pulse)) return math.floor(1000000/(frequency*samples_per_pulse))
@@ -53,52 +54,71 @@ def do_adc(adcpin=28, duty_cycle = 0.5, frequency = 2000, samples_per_pulse = 10
# == HTTP Stuff == # # == HTTP Stuff == #
# HTML template for the webpage # HTML template for the webpage
def default_webpage(): header = f"""
template = f"""
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Power Analysis Tool LFGGGGg</title> <title>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="preload" href="http://10.0.0.80/ComicCode-Regular.woff2" as="font" type="font/woff2" crossorigin>
<style>
body {{
font-family: 'Comic Code';
font-weight: normal;
font-style: normal;
}}
form, div {{
width: 80%;
margin: auto;
}}
h1 {{
font-size: 1.15em;'
}}
form input[type='number'] {{
width: 3.6em;
}}
</style>
</head> </head>
<body> <body>
<h1>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</h1> """
footer = f"""
</body>
</html>
"""
def default_webpage():
template = f"""
{header}
<form action="/action"> <form action="/action">
<b>Clock Control Config</b><br> <h1>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</h1>
<input id="duty_cycle" name="duty_cycle" type="range" min="0" max="1" step="0.01" value="0.5"> <output id="duty_cycle_output">50%</output> Duty Cycle (% of time clock is on)<br><br> <b>Config:</b><br>
<input type="number" name="freq" value="2000"> Frequency (Hz aka number of pulses per second)<br><br> Duty Cycle<br><input id="duty_cycle" name="duty_cycle" type="range" min="0" max="1" step="0.01" value="0.5"> <output id="duty_cycle_output">50%</output><br><br>
<b>Samplerate Config:</b><br> Frequency (Hz)<br><input type="number" size="5" name="freq" value="2000"><br><br>
<input type="number" id="samples_per_pulse" name="samples_per_pulse" value="5"> Samples Per Manual Clock Pulse<br><br> Samples Per Clock Pulse:<br> <input type="number" size="5" id="samples_per_pulse" name="samples_per_pulse" value="5"><br><br>
<input type="submit" value="Go, Baby, Go!"> <input type="submit" value="Go, Baby, Go!">
</form> </form>
<script> <script>
const value = document.querySelector("#duty_cycle_output"); const value = document.querySelector("#duty_cycle_output");
const input = document.querySelector("#duty_cycle"); const input = document.querySelector("#duty_cycle");
value.textContent = input.value;
value.textContent = "50%"; // set default for some reason? fuck javascript
input.addEventListener("input", (event) => {{ input.addEventListener("input", (event) => {{
value.textContent = (event.target.value*100)+"%"; value.textContent = (event.target.value*100)+"%";
}}); }});
</script> </script>
</body> {footer}
</html>
""" """
return str(template) return str(template)
# us of sleep calculate4d by floor(1000000 / (frequency_in_Hz * samples_per_pulse))
def running_webpage(outpin = 20, adcpin = 28, duty_cycle = 0.5, frequency = 2000, samples_per_pulse = 100): def running_webpage(outpin = 20, adcpin = 28, duty_cycle = 0.5, frequency = 2000, samples_per_pulse = 100):
dutyy = duty_cycle*100 dutyy = duty_cycle*100
us_sample = us_samples(frequency, samples_per_pulse) us_sample = us_samples(frequency, samples_per_pulse)
template = f""" template = f"""
<!DOCTYPE html> {header}
<html> <div id="sillyrunninfg">
<head>
<title>RUNNING - Power Analysis Tool LFGGGGg</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</h1> <h1>SillyFilly Pi Pico Power Analysis Tool (LFFGGGGG)</h1>
<h2>WE RUNNING NOWWWWW LFGGGGGGGGGGGGG</h2> <h2>WE RUNNING NOWWWWW LFGGGGGGGGGGGGG</h2>
<p> <p>
@@ -110,8 +130,8 @@ def running_webpage(outpin = 20, adcpin = 28, duty_cycle = 0.5, frequency = 2000
Delay Between Samples: <b>{us_sample}us</b><br><br> Delay Between Samples: <b>{us_sample}us</b><br><br>
<b>LFGGGGGGGG FRONG</b> <b>LFGGGGGGGG FRONG</b>
</p> </p>
</body> </div>
</html> {footer}
""" """
return str(template) return str(template)
@@ -137,7 +157,6 @@ if wlan.status() != 3:
else: else:
print('Connection successful!') print('Connection successful!')
network_info = wlan.ifconfig() network_info = wlan.ifconfig()
#print('IP address:', network_info[0])
print(f"\n\nOpen web browser and navigate to http://{network_info[0]}\n\n") print(f"\n\nOpen web browser and navigate to http://{network_info[0]}\n\n")
# Set up socket and start listening # Set up socket and start listening
@@ -187,10 +206,10 @@ while True:
response = running_webpage() response = running_webpage()
else: else:
response = default_webpage() response = default_webpage()
# Send the HTTP response and close the connection # Send the HTTP response and close the conn
conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
conn.send(response) conn.send(response)
conn.close() conn.close()
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB