diff --git a/src/DEMO-SD-Card/DATA/startup.msg b/src/DEMO-SD-Card/DATA/startup.msg new file mode 100644 index 0000000..4ff689b --- /dev/null +++ b/src/DEMO-SD-Card/DATA/startup.msg @@ -0,0 +1,7 @@ +************************ +* DHBW HW-Hacking DEMO * +************************ + +This hardware is just for hacking and having fun :-) + +For more information => Christopher Scheuring \ No newline at end of file diff --git a/src/DEMO-SD-Card/sd-card-root b/src/DEMO-SD-Card/sd-card-root new file mode 100644 index 0000000..e69de29 diff --git a/src/DHBW_HW_Challange_2022.py b/src/DHBW_HW_Challange_2022.py new file mode 100644 index 0000000..9e82026 --- /dev/null +++ b/src/DHBW_HW_Challange_2022.py @@ -0,0 +1,407 @@ +################################################################################ +# This is an Demo Application for analysing SPI and I2C access. +# It reads content from the SPI attached SD-Card and writes the sensor values +# of the I2C attached BMP180 and the values from the installed fotoresistor. +# +# For Demo, a tty TX access is possible and the SPI and I2C communication +# could analyzed by additional header pins. +# +# +# Copyright 2020 by Christopher Scheuring +# License: GPLv3 (https://www.gnu.org/licenses/gpl-3.0.de.html) +# +# +################################################################################ + +from machine import Pin, SPI, I2C, ADC +import machine, sdcard, os, esp32, time, random, gc +from bmp180 import BMP180 + +gc.collect() # make some room + +## timer handling +timer_measure = machine.Timer(0) +timer_led = machine.Timer(1) +timer_keypadtimeout = machine.Timer(3) + +# Global variables +interruptKeyPadTimeout = False + +temperature = 0 +fotoresistorValue = -1 +keyPadActive = False + +## setting up everything +adc = ADC(Pin(34)) # create an ADC object acting on a pin +adc.atten(ADC.ATTN_11DB) # 3.3V max + +## define switch pins +sw1_p = 32 +sw2_p = 33 +## int buttons (pull-up) +sw1 = Pin(sw1_p, Pin.IN) +sw2 = Pin(sw2_p, Pin.IN) + +# init green led +led_gn_p = 21 +led_gn = Pin(led_gn_p, Pin.OUT) +led_gn.off() # switch on led - inverted logic! + +# init red led +led_rd_p = 22 +led_rd = Pin(led_rd_p, Pin.OUT) +led_rd.on() # switch off led - inverted logic! + +# init yellow led - used for key pad usage +led_ye_p = 17 +led_ye = Pin(led_ye_p, Pin.OUT) +led_ye.on() # switch off led - inverted logic! + +## init key pad +# Connections left to right on KeyPad +# 0 1 2 3 4 5 6 7 +# 13 12 14 27 15 02 04 16 + +# Set up Rows +rows = [] +for p in [13, 12, 14, 27]: + row = Pin(p, Pin.OUT) + rows.append(row) +# anodes OFF +for i in range(4): + rows[i].off() + +# Set up columns +cols = [] +for p in [15, 02, 04, 16]: + col = Pin(p, Pin.IN, Pin.PULL_DOWN) + cols.append(col) + + +# init spi sd-card - exit on error +try: + spi = SPI(2, baudrate=10000000, polarity=0, phase=0, sck=machine.Pin(18), mosi=machine.Pin(23), miso=machine.Pin(19)) + sd = sdcard.SDCard(spi, machine.Pin(5)) + os.mount(sd, '/sd') +except: + print ("*** ERROR - could not init SPI sd-card ****") + print ("exiting...") + #sys.exit(1) + input() # the code just "stops" until some input is done... + +# init spi sd-card - exit on error +try: + i2c = I2C(1, scl=Pin(25), sda=Pin(26), freq=100000) + bmp180 = BMP180(i2c) +except: + print ("*** ERROR - could not init I2C BMP180 ****") + print ("exiting...") + #sys.exit(1) + input() # the code just "stops" until some input is done... + + +## some defs +#def sigint_handler(signal, frame): +# print ("KeyboardInterrupt is caught") +# #sys.exit(0) +#signal.signal(signal.SIGINT, sigint_handler) + +# time measure handling +def handleInterruptMeasure(timer_measure): + # global stuff + global fotoresistorValue + global pinPadActive + global myBMPlog + global myFRlog + global keyPadActive + global temperature + + # get the time stamp + tstamp = time.time() + + # get the sensor values + try: + temperature = bmp180.temperature + pressure = bmp180.pressure + altitude = bmp180.altitude + except: + temperature = "NaN" + pressure = "NaN" + altitude = "NaN" + try: + i2c = I2C(1, scl=Pin(25), sda=Pin(26), freq=100000) + bmp180 = BMP180(i2c) + temperature = bmp180.temperature + pressure = bmp180.pressure + altitude = bmp180.altitude + except: + print("*** Could not access Sensor 1 :: INIT Sensor 1 in progress ***") + + # write content to the log files + try: + bmplog = "{}:{}:{}:{}\n".format(tstamp, temperature, pressure, altitude) + myBMPlog.write(bmplog) + frlog = "{}:{}\n".format(tstamp, fotoresistorValue) + myFRlog.write(frlog) + # flush the files + myBMPlog.flush() + myFRlog.flush() + except: + try: + spi = SPI(2, baudrate=10000000, polarity=0, phase=0, sck=machine.Pin(18), mosi=machine.Pin(23), miso=machine.Pin(19)) + sd = sdcard.SDCard(spi, machine.Pin(5)) + os.mount(sd, '/sd') + myBMPlog = open("/sd/LOG/BMP180.log", "w") + myFRlog = open("/sd/LOG/FOTORE.log", "w") + except: + print("*** Could not access flash memory :: INIT flash memory in progress***") + + # print the values + # suspress if key pad is active + if keyPadActive == False: + print("Temperature: ", temperature, "Air pressure: ", pressure, "Altitude: ", altitude) + print("Fotoresistor Value: " , fotoresistorValue) + +#flash red led "count" with "wait" in sec +def flashRedLed(count, wait): + i = 0 + while i <= count: + if led_rd.value(): + led_rd.off() + else: + led_rd.on() + time.sleep(wait) + i = i + 1 + # turn led off + led_rd.on() + +#timer blinkin led +def handleInterruptLED(timer_led): + if led_gn.value(): + led_gn.off() + else: + led_gn.on() + ## this of for polling the fotoresistor every secound + # this value will be used for the blocking key pad activation + global fotoresistorValue + fotoresistorValue = adc.read() + +#timer KeyPad timeout +def handleInterruptKeyPadTimeout(timer_keypadtimeout): + global interruptKeyPadTimeout + interruptKeyPadTimeout = True + print("KeyPad Timeout") + # stop timer for key pad timeout + timer_keypadtimeout.deinit() + + +## key pad stuff +def getkey(): # Returns -999 or key value + foo = 0 + values = [1,2,3,10, 4,5,6,11, 7,8,9,12, 14,0,15,13] + val = -999 # Error value for no key press + for count in range(10): # Try to get key press 10 times + for r in range(4): # Rows, one at a time + rows[r].on() # row HIGH + for c in range(4): # Test columns, one at a time + if cols[c].value() == 1: # Is column HIGH? + p = r * 4 + c # Pointer to values list + val = values[p] + count = 11 # This stops looping + led_ye.off() # Flash LED ON if key pressed + rows[r].off() # row LOW + time.sleep(0.2) # Debounce + led_ye.on() # LED OFF + return val + +def getvalue(digits): # Number of digits + result = 0 + count = 0 + while True: + x = getkey() + if x != -999 and x < 10: # Check if numeric key pressed + result = result * 10 + x + #print(result) + count = count + 1 + if count == digits: + return result + + +# sd card print directory +def print_directory(path, tabs = 0): + for file in os.listdir(path): + stats = os.stat(path+"/"+file) + filesize = stats[6] + isdir = stats[0] & 0x4000 + + if filesize < 1000: + sizestr = str(filesize) + " byte" + elif filesize < 1000000: + sizestr = "%0.1f KB" % (filesize/1000) + else: + sizestr = "%0.1f MB" % (filesize/1000000) + + prettyprintname = "" + for i in range(tabs): + prettyprintname += " " + prettyprintname += file + if isdir: + prettyprintname += "/" + print('{0:<40} Size: {1:>10}'.format(prettyprintname, sizestr)) + + # recursively print directory contents + if isdir: + print_directory(path+"/"+file, tabs+1) + + +############################################################################### +## the main code +# print a welcome message :-) +print("\n") +try: + myFile = open("/sd/DATA/startup.msg", "r") + message = myFile.read() + print(message) + myFile.close() +except: + print("Could not open file /sd/DATA/startup.msg") + +print("\n") +print("Files on SPI Flash Memory:") +print("==========================") +print_directory("/sd") +print("Init Flash done...") + +# for better "doing" a race condition for file access interupt ;-) +time.sleep(0.5) +print("Start programm") +## open the log-files +# file handle without try to run into an exception to get the python shell +# this is an enhanced challange! +myBMPlog = open("/sd/LOG/BMP180.log", "w") +myFRlog = open("/sd/LOG/FOTORE.log", "w") + +# At this point we whant execption handling - without the file system can become broken! +try: + # write some init stuff into the file + bmplog = "Timestamp:Temperature:Pressure:Altidude\n" + myBMPlog.write(bmplog) + frlog = "Timestamp:Fotoresistor\n" + myFRlog.write(frlog) + myBMPlog.flush() + myFRlog.flush() + # generate a random pin everytime at sartup: 4 digits+[A|B|C|D] for key pad usage + pin = ''.join([random.choice('0123456789') for _ in range(4)]) + random.choice('ABCD') + #print(pin) + myPIN = open("/sd/.SECRET/.secret", "w") + myPIN.write(pin) + myPIN.close() +except: + print ("*** ERROR accessing flash memory ****") + print ("exiting...") + #sys.exit(1) + input() # the code just "stops" until some input is done... + + +## timer setup +timer_measure.init(period=2000, mode=machine.Timer.PERIODIC, callback=handleInterruptMeasure) +timer_led.init(period=750, mode=machine.Timer.PERIODIC, callback=handleInterruptLED) + +pinEntry="" + +############################################################################### +## and run in a loop :-) +while True: + # do something usefull... ;-) + + # only acitvate the pin entry mode, if the light sensor is covered + # and the sw1 is pressed. + if fotoresistorValue<=15 and sw1.value(): + print("Case is closed :: Start KeyPad activation for 10 seconds.") + # start timer for key pad timeout + interruptKeyPadTimeout = False + # max 10 sec possible because of "ampy.pyboard.PyboardError: timeout waiting for first EOF reception" + timer_keypadtimeout.init(period=10000, mode=machine.Timer.PERIODIC, callback=handleInterruptKeyPadTimeout) + + keyPadActive = True + + characters =["1","2","3","4","5","6","7","8","9","A","B","C","D","*","#","0"] + running = True + pinEntry = "" + print("Enter Pin (Confirm with #-Key):") + while running: + x = getkey() + if x != -999: # A key has been pressed! + if x == 15: + running = False + else: + # only store the digits and A-D - but not the # key + pinEntry = pinEntry + characters[x-1] + # echo the entered keys as addtional feedback + print(pinEntry) + # check if key pad entry timeout is true + if interruptKeyPadTimeout == True: + running = False + + print(pinEntry) + led_ye.on() # switch led off + + if pinEntry == pin: + print("\nEntered Pin OK ::: Entering Admin Mode") + print("\nYou have found the correct switch usage and identifyed to cover the light\nsensor, to enable the PIN Entry Mode.") + print("\nCongratz: You have solved the Admin-Menue Challange :-)") + print("\n\nNothing more to do here - just wait 2 seconds") + time.sleep(2) + #break + else: + # stop timer for key pad timeout + timer_keypadtimeout.deinit() + keyPadActive = False + interruptKeyPadTimeout = False + print("*** WRONG PIN ***") + flashRedLed(10,0.1) + #time.sleep(0.5) + elif fotoresistorValue>15 and sw1.value(): + print("Case is open - no Pin entry possible!") + flashRedLed(10,0.1) + time.sleep(1) + elif fotoresistorValue==4095 and sw2.value(): + print("\nEntering hidden REPL prompt (micropython console)...") + print("\nYou have found the correct switch usage and identifyed to flash the light\nsensor, to enable this hiddin function.") + print("\nCongratz: You have solved the Hidden-Function Challange :-)") + print("\n\nYou will get an REPL console.\nFor restart, just press the reset button of the ESP32 Wroom Shield.") + print("\n\nEnhanced Challange:\nTry to enable the RX-Data Pin for getting complete REPL access!") + print("Hint: Maybe you need a third \"hand\" and ask for aditional stuff ;-)") + + timer_led.deinit() + # fast blinking green led :) + timer_led.init(period=100, mode=machine.Timer.PERIODIC, callback=handleInterruptLED) + break + else: + # stop timer for key pad timeout + timer_keypadtimeout.deinit() + keyPadActive = False + interruptKeyPadTimeout = False + + ## just for Demo! + if float(temperature) > 80.0: + print("\n\n*** Hidden Demo Function :: TO HOT ***\n\n") + print("I'm gone :-|") + # verry fast blinking green led :) + + timer_measure.deinit() + timer_led.init(period=50, mode=machine.Timer.PERIODIC, callback=handleInterruptLED) + flashRedLed(40,0.1) + break + + if float(temperature) < -30.0: + print("\n\n*** Hidden Demo Function :: TO COLD ***\n\n") + print("I'm freezing :-|") + # verry slow blinking green led :) + timer_measure.deinit() + timer_led.init(period=2000, mode=machine.Timer.PERIODIC, callback=handleInterruptLED) + break + + # time.sleep(0.5) + +# end of main() \ No newline at end of file diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..38e6776 --- /dev/null +++ b/src/README.md @@ -0,0 +1,7 @@ +# Code used by Hardware Hacking 101 + +This directory contains the used code for the hacking challenge, a function test of the board, the needed libs. + +The directory DEMO-SD-Card contains the used directory structure of the sd-card which is attached by the SPI card reader. The sd-card must the vfat formatted and the content of the DEMO-SD-Card must be copied inside the root of the sd-card. + +The code is licensed under the GPLv3 (https://www.gnu.org/licenses/gpl-3.0.de.html) - **except** the code of the files ./lib/bmp180.py and ./lib/sdcard.py diff --git a/src/dhbw_esp32_function_test.py b/src/dhbw_esp32_function_test.py new file mode 100644 index 0000000..1595203 --- /dev/null +++ b/src/dhbw_esp32_function_test.py @@ -0,0 +1,266 @@ +#### +# Test script for functional testing +# DHBW Security Testing Micropython Hardware +# +# just execute non-persisten on ESP32 target +# e.g. ampy -p /dev/ttyUSB0 run dhbw_esp32_function_test.py +# +# A vfat formated sd-card must be present! +# +# Following python code must be persisten on target, +# to run this test script +# * bmp180.py +# * sdcard.py +# +# Copyright 2020 by Christopher Scheuring +# License: GPLv3 (https://www.gnu.org/licenses/gpl-3.0.de.html) +# +#### + +import machine, time, gc, sdcard, os, esp32 +from machine import Pin, ADC, I2C, SPI +from bmp180 import BMP180 + + +#### +# Simple Button and LED test +# yellow led will blink +# red + green will be off button is pressed +# runs 10 time and waits for next test + +print("Run Button and LED Test (5 times):") + +gc.collect() # make some room + +## define led pins +led_gr_p = 21 +led_re_p = 22 +led_ye_p = 17 + +## define switch pins +sw1_p = 32 +sw2_p = 33 + + +## init leds +led_gr = Pin(led_gr_p, Pin.OUT) +led_gr.off() # switch on led - inverted logic! + +led_re = Pin(led_re_p, Pin.OUT) +led_re.off() # switch on led - inverted logic! + +led_ye = Pin(led_ye_p, Pin.OUT) +led_ye.off() # switch on led - inverted logic! + + +## int buttons (pull-up) +sw1 = Pin(sw1_p, Pin.IN) +sw2 = Pin(sw2_p, Pin.IN) + +cnt = 0 +while cnt < 5: + if sw1.value(): + print(" SW1 true") + led_re.on() + else: + print(" SW1 false") + led_re.off() + if sw2.value(): + print(" SW2 true") + led_gr.on() + else: + print(" SW2 false") + led_gr.off() + + # toggle led + if led_ye.value(): + led_ye.off(); + else: + led_ye.on(); + + cnt = cnt + 1 + time.sleep(0.5) + +print("Finished Button and LED Test") +time.sleep(1) + + +#### +# Simple Fotoresistor Test +# Just displays the changed values for 10 times testing + +print("Run Fotoresistor Test (10 times):") + +gc.collect() # make some room + +adc = ADC(Pin(34)) # create an ADC object acting on a pin +adc.atten(ADC.ATTN_11DB) # 3.3V max + +cnt = 0 +while cnt < 10: + print(" Analog Value: " , adc.read()) + cnt = cnt + 1 + time.sleep(0.5) + +print("Finished Fotoresistor Test.") +time.sleep(1) + +#### +# Simple BMP180 Test +# Just displays the read values 5 times testing + +print("Run BMP180 Test (5 times):") + +gc.collect() # make some room + +try: + i2c = I2C(1, scl=Pin(25), sda=Pin(26), freq=100000) + + bmp180 = BMP180(i2c) + #bmp180.oversample_sett = 2 + #bmp180.baseline = 101325 + + cnt = 0 + while cnt < 5: + print(" temperature: ", bmp180.temperature, " air pressure: ", bmp180.pressure, " altitude: ", bmp180.altitude) + cnt = cnt + 1 + time.sleep(0.5) + + print("Finished BMP180 Test.") + time.sleep(1) + +except: + print("*** ERROR BMP180 Test - I2C not working ***") + + +#### +# Simple SD-Card Test +# Just opens the SD-Card, adds a file and prints the dir listing + +print("Run SD-Card Test:") + +gc.collect() # make some room + +try: + spi = SPI(2, baudrate=10000000, polarity=0, phase=0, sck=machine.Pin(18), mosi=machine.Pin(23), miso=machine.Pin(19)) + sd = sdcard.SDCard(spi, machine.Pin(5)) + + os.mount(sd, '/sd') + + def print_directory(path, tabs = 0): + for file in os.listdir(path): + stats = os.stat(path+"/"+file) + filesize = stats[6] + isdir = stats[0] & 0x4000 + + if filesize < 1000: + sizestr = str(filesize) + " by" + elif filesize < 1000000: + sizestr = "%0.1f KB" % (filesize/1000) + else: + sizestr = "%0.1f MB" % (filesize/1000000) + + prettyprintname = "" + for i in range(tabs): + prettyprintname += " " + prettyprintname += file + if isdir: + prettyprintname += "/" + print('{0:<40} Size: {1:>10}'.format(prettyprintname, sizestr)) + + # recursively print directory contents + if isdir: + print_directory(path+"/"+file, tabs+1) + + with open("/sd/hello.txt", "w") as f: + f.write("Hello world!\r\n") + + print("Files on filesystem:") + print("====================") + print_directory("/sd") + print("") + + print("Finished SD-Card Test.") +except: + print("*** ERROR SD-Card Test - Missing SD-Card or write fail ***") + +time.sleep(1) + + +#### +# Simple KeyPad Test +# Checks the pressed buttons + +print("Run KeyPad Test - finish by pressing \"#\":") + +gc.collect() # make some room + +# Set up LED on pin 17 +led_pin = 17 + +led = Pin(led_pin, Pin.OUT) +led.on() # switch off led - inverted logic! + +# Set up Rows +rows = [] +for p in [13, 12, 14, 27]: + row = Pin(p, Pin.OUT) + rows.append(row) +# anodes OFF +for i in range(4): + rows[i].off() + +# Set up columns +cols = [] +for p in [15, 02, 04, 16]: + col = Pin(p, Pin.IN, Pin.PULL_DOWN) + cols.append(col) + +def getkey(): # Returns -999 or key value + values = [1,2,3,10, 4,5,6,11, 7,8,9,12, 14,0,15,13] + val = -999 # Error value for no key press + for count in range(10): # Try to get key press 10 times + for r in range(4): # Rows, one at a time + rows[r].on() # row HIGH + for c in range(4): # Test columns, one at a time + if cols[c].value() == 1: # Is column HIGH? + p = r * 4 + c # Pointer to values list + val = values[p] + count = 11 # This stops looping + led.off() # Flash LED ON if key pressed + rows[r].off() # row LOW + time.sleep(0.2) # Debounce + led.on() # LED OFF + return val + +def getvalue(digits): # Number of digits + result = 0 + count = 0 + while True: + x = getkey() + if x != -999 and x < 10: # Check if numeric key pressed + result = result * 10 + x + print(result) + count = count + 1 + if count == digits: + return result + +# +++++ Main +++++ +print("Press 4 numeric (BLUE) keys") +y = getvalue(4) +print('\n',y) + +print("\nPress any of the keys\n # halts the program") + +characters =["1","2","3","4","5","6","7","8","9","A","B","C","D","*","#","0"] +running = True +while running: + x = getkey() + if x != -999: # A key has been pressed! + print(characters[x-1]) + if x == 15: + running = False + +led.on() + +print("Finished KeyPad Test - noting to do anymore.") \ No newline at end of file