Next
This commit is contained in:
@@ -2,3 +2,4 @@
|
|||||||
.micropico
|
.micropico
|
||||||
PiPicoPATLFGGGGG.code-workspace
|
PiPicoPATLFGGGGG.code-workspace
|
||||||
main_dev.py
|
main_dev.py
|
||||||
|
ComicCode-Regular.*
|
||||||
+12
@@ -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.
|
||||||
|
|
||||||
@@ -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)
|
||||||
|

|
||||||
@@ -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 |
Reference in New Issue
Block a user