├── LICENSE.md ├── README.md └── panic_bcast.py /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, Niklas Femerstrand 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 15 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 18 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # panic_bcast # 2 | 3 | panic_bcast is a network protocol panic button operating decentralized through UDP broadcasts and HTTP. It’s intended to act a panic button in a sensitive network making it harder to perform cold boot attacks. A serious freedom fighter will run something like this on all nodes in the computerized network. 4 | 5 | panic_bcast was written with the intention to support any form of UNIX that can run Python. It has been successfully tested on FreeBSD and Linux. 6 | 7 | To trigger the panic signal over HTTP simply request http://...:8080/panic from a machine that is running panic_bcast. Which ever will do. 8 | 9 | ## How it works ## 10 | 11 | 1. An activist has uninvited guests at the door 12 | 2. The activist sends the panic signal, a UDP broadcast, with panic_bcast 13 | 3. Other machines in the network pick up the panic signal 14 | 4. Once panic_bcast has picked the panic signal it kills truecrypt and powers off the machine. 15 | 16 | ## Authentication ## 17 | 18 | If you want you can append the panic signal with a required key. Just execute the script with the -k option. When using the key it is appended to the string "panic"; if your key happens to be "_banana" then the panic signal will respectively be "panic_banana". The panic signal is then sent over the network as a MD5 checksum. Consequently you have to start the script with the same key value on all instances in the network. 19 | 20 | For script help execute with the --help parameter. 21 | 22 | 23 | Please note that panic_bcast is a beta and more sophisticated ways to prevent cold boot attacks are planned. You can view these plans by searching for the word "TODO" in the source code. 24 | 25 | Remember kids: there's no home for swap in opsec. 26 | -------------------------------------------------------------------------------- /panic_bcast.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2.7 2 | # Copyright (c) 2012, Niklas Femerstrand 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions 7 | # are met: 8 | # 9 | # Redistributions of source code must retain the above copyright notice, 10 | # this list of conditions and the following disclaimer. 11 | # Redistributions in binary form must reproduce the above copyright notice, 12 | # this list of conditions and the following disclaimer in the documentation 13 | # and/or other materials provided with the distribution. 14 | # 15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 16 | # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 17 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 19 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | import re 27 | import os 28 | import md5 29 | import socket 30 | import threading 31 | import BaseHTTPServer 32 | from optparse import OptionParser 33 | from SimpleHTTPServer import SimpleHTTPRequestHandler 34 | from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer 35 | 36 | argparse = OptionParser() 37 | argparse.add_option("-k", "--key", dest="key", 38 | help = "Optional, when set it adds a key to the panic signal.", 39 | metavar="") 40 | argparse.add_option("-p", "--port", dest="port", 41 | help = "HTTP port to use", 42 | metavar="") 43 | 44 | args = argparse.parse_args() 45 | 46 | global key 47 | key = args[0].key or "" 48 | 49 | global port 50 | port = int(args[0].port or 8080) 51 | 52 | global signal 53 | signal = "/\\x" 54 | signal += "\\x".join(x.encode("hex") for x in md5.new("panic" + key).digest()) 55 | 56 | # Basic HTTP server that listens to GET /panic and triggers panic. 57 | # Written to provide a standardized interface for panic triggering. 58 | # To trigger panic through HTTP simply request http://localhost:port/panic 59 | class panicHandler(BaseHTTPRequestHandler): 60 | def do_GET(self): 61 | req = "/\\x" + "\\x".join(x.encode("hex") for x in md5.new(re.sub("^\/", "", self.path)).digest()) 62 | if req == signal: 63 | sendSignal() 64 | 65 | def httpd(): 66 | s = HTTPServer(('', port), panicHandler) 67 | s.serve_forever() 68 | 69 | # TODO: Extend with a C lib that iterates through used physmem addresses and 70 | # overwrites values in a prio order before triggering poweroff. 71 | # TODO: Use mountedDrives() to iterate and eject (crypto) mounts 72 | def treatPanic(): 73 | os.popen("truecrypt -d") 74 | # Linux, possibly more 75 | os.popen("shutdown -P now") 76 | # FreeBSD, possibly more 77 | os.popen("shutdown -p now") 78 | 79 | def sigListener(): 80 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 81 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 82 | s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 83 | s.bind(("", 1337)) # Listen on all devices 84 | 85 | while True: 86 | try: 87 | message, address = s.recvfrom(65) 88 | if message == signal: 89 | treatPanic() 90 | except: 91 | pass 92 | 93 | def bcast(): 94 | bcast = os.popen("ifconfig | grep -o \"broadcast [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\"").read() 95 | bcast = bcast.replace("broadcast ", "") 96 | return bcast 97 | 98 | def sendSignal(): 99 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 100 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 101 | s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 102 | s.sendto(signal, (bcast(), 1337)) 103 | s.close() 104 | return 0 105 | 106 | 107 | httpd = threading.Thread(name="httpd", target=httpd) 108 | httpd.start() 109 | sigListener = threading.Thread(name="sigListener", target=sigListener) 110 | sigListener.start() 111 | --------------------------------------------------------------------------------