├── LICENSE
├── README.md
├── cs
├── App.xaml
├── App.xaml.cs
├── Assets
│ ├── LargeTile.scale-100.png
│ ├── LargeTile.scale-200.png
│ ├── LargeTile.scale-400.png
│ ├── SmallTile-sdk.altform-lightunplated_targetsize-16.png
│ ├── SmallTile-sdk.altform-lightunplated_targetsize-256.png
│ ├── SmallTile-sdk.altform-lightunplated_targetsize-48.png
│ ├── SmallTile-sdk.altform-unplated_targetsize-16.png
│ ├── SmallTile-sdk.altform-unplated_targetsize-256.png
│ ├── SmallTile-sdk.altform-unplated_targetsize-48.png
│ ├── SmallTile-sdk.scale-100.png
│ ├── SmallTile-sdk.scale-200.png
│ ├── SmallTile-sdk.scale-400.png
│ ├── SmallTile-sdk.targetsize-16.png
│ ├── SmallTile-sdk.targetsize-256.png
│ ├── SmallTile-sdk.targetsize-48.png
│ ├── SmallTile.scale-100.png
│ ├── SmallTile.scale-200.png
│ ├── SmallTile.scale-400.png
│ ├── Splash-sdk.scale-100.png
│ ├── Splash-sdk.scale-200.png
│ ├── Splash-sdk.scale-400.png
│ ├── StoreLogo-sdk.scale-100.png
│ ├── StoreLogo-sdk.scale-200.png
│ ├── StoreLogo-sdk.scale-400.png
│ ├── WideTile.scale-100.png
│ ├── WideTile.scale-200.png
│ ├── WideTile.scale-400.png
│ ├── applause.mp3
│ ├── ble_hackme.png
│ ├── nrf_connect_advertisement_data_format_display.png
│ ├── nrf_connect_advertisement_details.png
│ ├── nrf_connect_advertisement_flags.png
│ ├── nrf_connect_battery_level.png
│ ├── nrf_connect_filter_rssi.png
│ ├── nrf_connect_generic_access_characteristics.png
│ ├── nrf_connect_heart_rate_notification.png
│ ├── nrf_connect_ibeacon_advertisement.png
│ ├── nrf_connect_ibeacon_advertisement_as_ble41.png
│ ├── nrf_connect_ibeacon_raw_explained.png
│ ├── nrf_connect_import_macro.png
│ ├── nrf_connect_macro_add_delay.png
│ ├── nrf_connect_macro_available.png
│ ├── nrf_connect_macro_delay_set_ms.png
│ ├── nrf_connect_macro_export_to_xml.png
│ ├── nrf_connect_macro_functionality.png
│ ├── nrf_connect_macro_functionality_small.png
│ ├── nrf_connect_macro_menu.png
│ ├── nrf_connect_macro_pass_brute.png
│ ├── nrf_connect_macro_repeat.png
│ ├── nrf_connect_macro_save.png
│ ├── nrf_connect_macro_send_pass_single.png
│ ├── nrf_connect_macro_start_recording.png
│ ├── nrf_connect_microsoft_advertisement.png
│ ├── nrf_connect_notify_arrow.png
│ ├── nrf_connect_quicklock_history_service.png
│ ├── nrf_connect_raw_advertisement_desc.png
│ ├── nrf_connect_read_arrow.png
│ ├── nrf_connect_scan_desc.png
│ ├── nrf_connect_text_descriptor.png
│ ├── nrf_connect_write_01.png
│ ├── nrf_connect_write_arrow.png
│ ├── nrf_connect_write_hello_command.png
│ ├── nrf_connect_write_text_option.png
│ ├── nrf_connect_write_value_form.png
│ ├── quicklock_date_format_decompiled.png
│ ├── quicklock_sniff.jpg
│ ├── rick.wmv
│ ├── smartlockpicking.png
│ ├── squareTile-sdk.scale-100.png
│ ├── squareTile-sdk.scale-200.png
│ ├── squareTile-sdk.scale-400.png
│ ├── trophy.jpg
│ ├── wireshark_apply_as_column.png
│ ├── wireshark_apply_filter_write_request.png
│ ├── wireshark_btatt_filter.png
│ ├── wireshark_btatt_filter_small.png
│ ├── wireshark_btatt_filter_smaller.png
│ ├── wireshark_filter_write_request.png
│ ├── wireshark_intro.png
│ ├── wireshark_new_column_value.png
│ └── wireshark_quicklock_authentication.png
├── BLE.cs
├── BLEServices
│ ├── BatteryLevelCharacteristic.cs
│ ├── BatteryService.cs
│ ├── CurrentTimeCharacteristic.cs
│ ├── CurrentTimeService.cs
│ ├── GenericGattCharacteristic.cs
│ ├── GenericGattService.cs
│ ├── HeartRateMeasurementCharacteristic.cs
│ ├── HeartRateService.cs
│ ├── Helpers.cs
│ ├── LightBulbColorCharacteristic.cs
│ ├── LightBulbService.cs
│ ├── LightBulbSwitchCharacteristic.cs
│ ├── LightBulbTTSCharacteristic.cs
│ ├── QuickLockAuthCharacteristic.cs
│ ├── QuickLockAuthStatusCharacteristic.cs
│ ├── QuickLockCommandCharacteristic.cs
│ ├── QuickLockHistoryControlCharacteristic.cs
│ ├── QuickLockHistoryDataCharacteristic.cs
│ ├── QuickLockHistoryService.cs
│ ├── QuickLockMainService.cs
│ ├── QuickLockOpenTimeCharacteristic.cs
│ ├── QuickLockUnlockStatusCharacteristic.cs
│ ├── QuickLockUsernameCharacteristic.cs
│ └── iBeacon.cs
├── BLE_Hackme.csproj
├── BLE_Hackme.sln
├── Constants.cs
├── MainPage.xaml
├── MainPage.xaml.cs
├── Package.appxmanifest
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── Scenarios
│ ├── Scenario_01_Compatibility.xaml
│ ├── Scenario_01_Compatibility.xaml.cs
│ ├── Scenario_02_Intro.xaml
│ ├── Scenario_02_Intro.xaml.cs
│ ├── Scenario_03_Advertisements.xaml
│ ├── Scenario_03_Advertisements.xaml.cs
│ ├── Scenario_04_Beacons.xaml
│ ├── Scenario_04_Beacons.xaml.cs
│ ├── Scenario_05_ManufacturerAdvertisements.xaml
│ ├── Scenario_05_ManufacturerAdvertisements.xaml.cs
│ ├── Scenario_06_Connections.xaml
│ ├── Scenario_06_Connections.xaml.cs
│ ├── Scenario_07_Read.xaml
│ ├── Scenario_07_Read.xaml.cs
│ ├── Scenario_08_Notifications.xaml
│ ├── Scenario_08_Notifications.xaml.cs
│ ├── Scenario_09_Descriptors.xaml
│ ├── Scenario_09_Descriptors.xaml.cs
│ ├── Scenario_10_Write.xaml
│ ├── Scenario_10_Write.xaml.cs
│ ├── Scenario_11_WriteCommand.xaml
│ ├── Scenario_11_WriteCommand.xaml.cs
│ ├── Scenario_12_Macros.xaml
│ ├── Scenario_12_Macros.xaml.cs
│ ├── Scenario_13_RGB.xaml
│ ├── Scenario_13_RGB.xaml.cs
│ ├── Scenario_14_PasswordBrute.xaml
│ ├── Scenario_14_PasswordBrute.xaml.cs
│ ├── Scenario_15_QuickLockReplay.xaml
│ ├── Scenario_15_QuickLockReplay.xaml.cs
│ ├── Scenario_16_QuickLockLogs.xaml
│ ├── Scenario_16_QuickLockLogs.xaml.cs
│ ├── Scenario_Summary.xaml
│ └── Scenario_Summary.xaml.cs
├── ScenariosConfiguration.cs
├── Styles
│ └── Styles.xaml
└── UserControls
│ ├── LightBulbUserControl.xaml
│ ├── LightBulbUserControl.xaml.cs
│ ├── ScenarioSubHeaderHints.xaml
│ ├── ScenarioSubHeaderHints.xaml.cs
│ ├── ScenarioSubHeaderIntro.xaml
│ ├── ScenarioSubHeaderIntro.xaml.cs
│ ├── ScenarioSubHeaderSimulatedDevice.xaml
│ ├── ScenarioSubHeaderSimulatedDevice.xaml.cs
│ ├── ScenarioSubHeaderSubmit.xaml
│ ├── ScenarioSubHeaderSubmit.xaml.cs
│ ├── ScenarioSubHeaderTask.xaml
│ ├── ScenarioSubHeaderTask.xaml.cs
│ ├── SmartLockUserControl.xaml
│ └── SmartLockUserControl.xaml.cs
└── logo.png
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Slawomir Jasek slawomir.jasek@smartlockpicking.com
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 |
5 | # Bluetooth Low Energy hardware-less HackMe
6 |
7 | The project aims to introduce the BLE protocol and its security basics.
8 | A standard Windows 10 computer with Bluetooth interface will simulate various BLE devices - on the radio layer working exactly as real ones.
9 | In a series of tasks with increasing level of complexity, allows to get familiar with BLE advertisements, beacons, connections, take control over talking BLE smart bulb, reverse-engineer the communication, brute force passwords, and even hack real smart lock.
10 |
11 |
12 | ## System requirements
13 |
14 | * Windows 10 Anniversary Edition
15 | * Bluetooth adapter - should work with most adapters built in standard laptops, not necessarily with external dongle
16 |
17 | The tasks are designed to be solved using free Android mobile application, connecting to the simulated devices via BLE (iOS has limited low level BLE features).
18 |
19 | It is also possible to use other BLE tools, for example running on Linux or Mac, however details are not covered in the HackMe instructions.
20 |
21 |
22 | ## Installation
23 |
24 | Binary version is available in Microsoft Store:
25 |
26 | [https://www.microsoft.com/store/apps/9N7PNVS9J1B7](https://www.microsoft.com/store/apps/9N7PNVS9J1B7)
27 |
28 | ## Building from source
29 |
30 | ### Build in Visual Studio
31 |
32 | For building from source, Microsoft Visual Studio is required (free, Community edition will work).
33 |
34 | 1. Start Microsoft Visual Studio and select **File** \> **Open** \> **Project/Solution**.
35 | 2. Double-click the Visual Studio Solution (.sln) file.
36 | 3. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
37 |
38 | ### Run the debug session
39 |
40 | To debug the application and then run it, press F5 or select Debug > Start Debugging. To run without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.
41 |
42 | Some debug information available in the "Output" section in Visual Studio.
43 |
44 |
45 | ## FAQ, more information
46 |
47 | Frequently Asked Questions, list of incompatible hardware: [https://github.com/smartlockpicking/BLE_HackMe/wiki/FAQ](https://github.com/smartlockpicking/BLE_HackMe/wiki/FAQ)
48 |
49 | More information: [www.smartlockpicking.com/ble_hackme](www.smartlockpicking.com/ble_hackme)
50 |
51 |
52 | ## License
53 |
54 | This application was developed by Slawomir Jasek slawomir.jasek@smartlockpicking.com.
55 |
56 | It is free software licensed under the MIT License.
57 |
58 | [](https://opensource.org/licenses/MIT)
59 |
60 |
61 | The code is partially based on Microsoft [Bluetooth LE Explorer](https://github.com/microsoft/BluetoothLEExplorer) and [Bluetooth LE Sample](https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/BluetoothLE).
62 |
--------------------------------------------------------------------------------
/cs/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/cs/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Windows.ApplicationModel.Activation;
3 | using Windows.UI.Xaml;
4 | using Windows.UI.Xaml.Controls;
5 | using Windows.UI.Xaml.Navigation;
6 |
7 | namespace BLE_Hackme
8 | {
9 | sealed partial class App : Application
10 | {
11 | ///
12 | /// Initializes the singleton application object. This is the first line of authored code
13 | /// executed, and as such is the logical equivalent of main() or WinMain().
14 | ///
15 | public App()
16 | {
17 | this.InitializeComponent();
18 | this.Construct();
19 | }
20 |
21 | ///
22 | /// Invoked when the application is launched normally by the end user. Other entry points
23 | /// will be used such as when the application is launched to open a specific file.
24 | ///
25 | /// Details about the launch request and process.
26 | protected override void OnLaunched(LaunchActivatedEventArgs e)
27 | {
28 |
29 | #if DEBUG
30 | if (System.Diagnostics.Debugger.IsAttached)
31 | {
32 | this.DebugSettings.EnableFrameRateCounter = false;
33 | }
34 | #endif
35 |
36 | Frame rootFrame = Window.Current.Content as Frame;
37 |
38 | // Do not repeat app initialization when the Window already has content,
39 | // just ensure that the window is active
40 | if (rootFrame == null)
41 | {
42 | // Create a Frame to act as the navigation context and navigate to the first page
43 | rootFrame = new Frame();
44 | // Set the default language
45 | rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
46 |
47 | rootFrame.NavigationFailed += OnNavigationFailed;
48 |
49 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
50 | {
51 | //TODO: Load state from previously suspended application
52 | }
53 |
54 | // Place the frame in the current Window
55 | Window.Current.Content = rootFrame;
56 | }
57 |
58 | if (rootFrame.Content == null)
59 | {
60 | // When the navigation stack isn't restored navigate to the first page,
61 | // configuring the new page by passing required information as a navigation
62 | // parameter
63 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
64 | }
65 |
66 | // Ensure the current window is active
67 | Window.Current.Activate();
68 |
69 | // in case LaunchActivatedEventArgs is needed
70 | LaunchCompleted(e);
71 | }
72 |
73 | private Frame CreateRootFrame()
74 | {
75 | Frame rootFrame = Window.Current.Content as Frame;
76 |
77 | // Do not repeat app initialization when the Window already has content,
78 | // just ensure that the window is active
79 | if (rootFrame == null)
80 | {
81 | // Create a Frame to act as the navigation context and navigate to the first page
82 | rootFrame = new Frame();
83 |
84 | // Set the default language
85 | rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
86 | rootFrame.NavigationFailed += OnNavigationFailed;
87 |
88 | // Place the frame in the current Window
89 | Window.Current.Content = rootFrame;
90 | }
91 |
92 | return rootFrame;
93 | }
94 |
95 | ///
96 | /// Invoked when Navigation to a certain page fails
97 | ///
98 | /// The Frame which failed navigation
99 | /// Details about the navigation failure
100 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
101 | {
102 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
103 | }
104 |
105 | // Add any application contructor code in here.
106 | partial void Construct();
107 |
108 | // Add any OnLaunched customization here.
109 | partial void LaunchCompleted(LaunchActivatedEventArgs e);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/cs/Assets/LargeTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/LargeTile.scale-100.png
--------------------------------------------------------------------------------
/cs/Assets/LargeTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/LargeTile.scale-200.png
--------------------------------------------------------------------------------
/cs/Assets/LargeTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/LargeTile.scale-400.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.altform-lightunplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.altform-lightunplated_targetsize-16.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.altform-lightunplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.altform-lightunplated_targetsize-256.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.altform-lightunplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.altform-lightunplated_targetsize-48.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.altform-unplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.altform-unplated_targetsize-16.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.altform-unplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.altform-unplated_targetsize-256.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.altform-unplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.altform-unplated_targetsize-48.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.scale-100.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.scale-200.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.scale-400.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.targetsize-16.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.targetsize-256.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile-sdk.targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile-sdk.targetsize-48.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile.scale-100.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile.scale-200.png
--------------------------------------------------------------------------------
/cs/Assets/SmallTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/SmallTile.scale-400.png
--------------------------------------------------------------------------------
/cs/Assets/Splash-sdk.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/Splash-sdk.scale-100.png
--------------------------------------------------------------------------------
/cs/Assets/Splash-sdk.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/Splash-sdk.scale-200.png
--------------------------------------------------------------------------------
/cs/Assets/Splash-sdk.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/Splash-sdk.scale-400.png
--------------------------------------------------------------------------------
/cs/Assets/StoreLogo-sdk.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/StoreLogo-sdk.scale-100.png
--------------------------------------------------------------------------------
/cs/Assets/StoreLogo-sdk.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/StoreLogo-sdk.scale-200.png
--------------------------------------------------------------------------------
/cs/Assets/StoreLogo-sdk.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/StoreLogo-sdk.scale-400.png
--------------------------------------------------------------------------------
/cs/Assets/WideTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/WideTile.scale-100.png
--------------------------------------------------------------------------------
/cs/Assets/WideTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/WideTile.scale-200.png
--------------------------------------------------------------------------------
/cs/Assets/WideTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/WideTile.scale-400.png
--------------------------------------------------------------------------------
/cs/Assets/applause.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/applause.mp3
--------------------------------------------------------------------------------
/cs/Assets/ble_hackme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/ble_hackme.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_advertisement_data_format_display.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_advertisement_data_format_display.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_advertisement_details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_advertisement_details.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_advertisement_flags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_advertisement_flags.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_battery_level.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_battery_level.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_filter_rssi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_filter_rssi.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_generic_access_characteristics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_generic_access_characteristics.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_heart_rate_notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_heart_rate_notification.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_ibeacon_advertisement.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_ibeacon_advertisement.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_ibeacon_advertisement_as_ble41.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_ibeacon_advertisement_as_ble41.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_ibeacon_raw_explained.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_ibeacon_raw_explained.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_import_macro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_import_macro.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_add_delay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_add_delay.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_available.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_available.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_delay_set_ms.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_delay_set_ms.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_export_to_xml.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_export_to_xml.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_functionality.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_functionality.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_functionality_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_functionality_small.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_menu.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_pass_brute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_pass_brute.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_repeat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_repeat.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_save.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_send_pass_single.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_send_pass_single.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_macro_start_recording.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_macro_start_recording.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_microsoft_advertisement.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_microsoft_advertisement.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_notify_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_notify_arrow.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_quicklock_history_service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_quicklock_history_service.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_raw_advertisement_desc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_raw_advertisement_desc.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_read_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_read_arrow.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_scan_desc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_scan_desc.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_text_descriptor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_text_descriptor.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_write_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_write_01.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_write_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_write_arrow.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_write_hello_command.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_write_hello_command.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_write_text_option.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_write_text_option.png
--------------------------------------------------------------------------------
/cs/Assets/nrf_connect_write_value_form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/nrf_connect_write_value_form.png
--------------------------------------------------------------------------------
/cs/Assets/quicklock_date_format_decompiled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/quicklock_date_format_decompiled.png
--------------------------------------------------------------------------------
/cs/Assets/quicklock_sniff.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/quicklock_sniff.jpg
--------------------------------------------------------------------------------
/cs/Assets/rick.wmv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/rick.wmv
--------------------------------------------------------------------------------
/cs/Assets/smartlockpicking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/smartlockpicking.png
--------------------------------------------------------------------------------
/cs/Assets/squareTile-sdk.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/squareTile-sdk.scale-100.png
--------------------------------------------------------------------------------
/cs/Assets/squareTile-sdk.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/squareTile-sdk.scale-200.png
--------------------------------------------------------------------------------
/cs/Assets/squareTile-sdk.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/squareTile-sdk.scale-400.png
--------------------------------------------------------------------------------
/cs/Assets/trophy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/trophy.jpg
--------------------------------------------------------------------------------
/cs/Assets/wireshark_apply_as_column.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/wireshark_apply_as_column.png
--------------------------------------------------------------------------------
/cs/Assets/wireshark_apply_filter_write_request.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/wireshark_apply_filter_write_request.png
--------------------------------------------------------------------------------
/cs/Assets/wireshark_btatt_filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/wireshark_btatt_filter.png
--------------------------------------------------------------------------------
/cs/Assets/wireshark_btatt_filter_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/wireshark_btatt_filter_small.png
--------------------------------------------------------------------------------
/cs/Assets/wireshark_btatt_filter_smaller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/wireshark_btatt_filter_smaller.png
--------------------------------------------------------------------------------
/cs/Assets/wireshark_filter_write_request.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/wireshark_filter_write_request.png
--------------------------------------------------------------------------------
/cs/Assets/wireshark_intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/wireshark_intro.png
--------------------------------------------------------------------------------
/cs/Assets/wireshark_new_column_value.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/wireshark_new_column_value.png
--------------------------------------------------------------------------------
/cs/Assets/wireshark_quicklock_authentication.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Assets/wireshark_quicklock_authentication.png
--------------------------------------------------------------------------------
/cs/BLEServices/BatteryLevelCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 |
8 |
9 | namespace BLE_Hackme.BLEServices
10 | {
11 | ///
12 | /// Implementation of the battery profile
13 | ///
14 | public class BatteryLevelCharacteristic : GenericGattCharacteristic
15 | {
16 |
17 | public int batteryLevelIndication;
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | /// The characteristic that this wraps
23 | public BatteryLevelCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
24 | {
25 | // generate random value 1-100%
26 | Random rnd = new Random();
27 | batteryLevelIndication = rnd.Next(1, 100);
28 | Value = BLEServices.Helpers.ToIBuffer(batteryLevelIndication);
29 | }
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/cs/BLEServices/BatteryService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.ComponentModel;
8 |
9 | namespace BLE_Hackme.BLEServices
10 | {
11 | ///
12 | /// Class for Battery Services
13 | ///
14 | public class BatteryService : GenericGattService
15 | {
16 | ///
17 | /// Name of the service
18 | ///
19 | public override string Name
20 | {
21 | get
22 | {
23 | return "Battery Service";
24 | }
25 | }
26 |
27 | ///
28 | /// Battery level
29 | ///
30 | private BatteryLevelCharacteristic batteryLevel;
31 |
32 | ///
33 | /// Gets or sets the battery level
34 | ///
35 | public BatteryLevelCharacteristic BatteryLevel
36 | {
37 | get
38 | {
39 | return batteryLevel;
40 | }
41 |
42 | set
43 | {
44 | if (batteryLevel != value)
45 | {
46 | batteryLevel = value;
47 | OnPropertyChanged(new PropertyChangedEventArgs("BatteryLevel"));
48 | }
49 | }
50 | }
51 |
52 | ///
53 | /// Asynchronous initialization
54 | ///
55 | /// Initialization Task
56 | public override async Task Init()
57 | {
58 | await CreateServiceProvider(GattServiceUuids.Battery);
59 |
60 | // Preparing the Battery Level characteristics
61 | GattLocalCharacteristicParameters batteryCharacteristicsParameters = PlainReadParameters;
62 |
63 | // Set the user descriptions
64 | // batteryCharacteristicsParameters.UserDescription = "Battery Level percentage remaining";
65 |
66 | // Create the characteristic for the service
67 | GattLocalCharacteristicResult result =
68 | await ServiceProvider.Service.CreateCharacteristicAsync(
69 | GattCharacteristicUuids.BatteryLevel,
70 | batteryCharacteristicsParameters);
71 |
72 | // Grab the characterist object from the service set it to the BatteryLevel property which is of a specfic Characteristic type
73 | GattLocalCharacteristic baseBatteryLevel = null;
74 | BLEServices.Helpers.GetCharacteristicsFromResult(result, ref baseBatteryLevel);
75 |
76 | if (baseBatteryLevel != null)
77 | {
78 | BatteryLevel = new BLEServices.BatteryLevelCharacteristic(baseBatteryLevel, this);
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/cs/BLEServices/CurrentTimeCharacteristic.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
9 | using Windows.Devices.Power;
10 | using Windows.Security.Authentication.Identity.Provider;
11 | using Windows.Storage.Streams;
12 | using Windows.System.Threading;
13 |
14 | namespace BLE_Hackme.BLEServices
15 | {
16 | public class CurrentTimeCharacteristic : GenericGattCharacteristic
17 | {
18 | private ThreadPoolTimer m_timeUpdate = null;
19 |
20 | public CurrentTimeCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
21 | {
22 | UpdateCurrentTimeValue();
23 | }
24 |
25 | public override void NotifyValue()
26 | {
27 | UpdateCurrentTimeValue();
28 | base.NotifyValue();
29 | }
30 |
31 | protected override bool ReadRequested(GattSession session, GattReadRequest request)
32 | {
33 | UpdateCurrentTimeValue();
34 | request.RespondWithValue(Value);
35 | return true;
36 | }
37 |
38 |
39 | protected override void Characteristic_SubscribedClientsChanged(GattLocalCharacteristic sender, object args)
40 | {
41 | lock (this)
42 | {
43 | if (sender.SubscribedClients.Count == 0)
44 | {
45 | if (m_timeUpdate != null)
46 | {
47 | m_timeUpdate.Cancel();
48 | m_timeUpdate = null;
49 | }
50 | }
51 | else if (m_timeUpdate == null)
52 | {
53 | m_timeUpdate = ThreadPoolTimer.CreatePeriodicTimer(
54 | (source) =>
55 | {
56 | UpdateCurrentTimeValue();
57 | NotifyValue();
58 | },
59 | // update time via notification every minute
60 | TimeSpan.FromMinutes(1));
61 | }
62 | }
63 |
64 | base.Characteristic_SubscribedClientsChanged(sender, args);
65 | }
66 |
67 | private void UpdateCurrentTimeValue()
68 | {
69 | // Quicklock stores data as seconds counted from 2000-01-01 00:00:00
70 | DateTime currentDateTime = DateTime.Now;
71 | DateTime quickLockEpochStart = new DateTime(2000,1,1);
72 |
73 | var currentSeconds = (int)(currentDateTime - quickLockEpochStart).TotalSeconds;
74 |
75 | Debug.WriteLine($"Current time for quicklock (seconds counted from 2000-01-01): {currentSeconds}");
76 |
77 | Value = Helpers.ToIBuffer(currentSeconds);
78 | }
79 |
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/cs/BLEServices/CurrentTimeService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
4 | using System.ComponentModel;
5 |
6 | namespace BLE_Hackme.BLEServices
7 | {
8 | ///
9 | /// Class for Current time service
10 | ///
11 | public class CurrentTimeService : GenericGattService
12 | {
13 | ///
14 | /// Name of the service
15 | ///
16 | public override string Name
17 | {
18 | get
19 | {
20 | return "Current Time Service (Quicklock)";
21 | }
22 | }
23 |
24 | ///
25 | /// Current time characteristic
26 | ///
27 | private GenericGattCharacteristic currentTime;
28 |
29 | ///
30 | /// Gets or sets the currentTime
31 | ///
32 | public GenericGattCharacteristic CurrentTime
33 | {
34 | get
35 | {
36 | return currentTime;
37 | }
38 |
39 | set
40 | {
41 | if (currentTime != value)
42 | {
43 | currentTime = value;
44 | OnPropertyChanged(new PropertyChangedEventArgs("CurrentTime"));
45 | }
46 | }
47 | }
48 |
49 | ///
50 | /// Asynchronous initialization
51 | ///
52 | /// Initialization Task
53 | public override async Task Init()
54 | {
55 | await CreateServiceProvider(GattServiceUuids.CurrentTime);
56 |
57 | GattLocalCharacteristicParameters currentTimeCharacteristicsParameters = PlainReadNotifyParameters;
58 | // Set the user descriptions
59 | currentTimeCharacteristicsParameters.UserDescription = "Current Time!";
60 |
61 |
62 | GattLocalCharacteristicResult result = await ServiceProvider.Service.CreateCharacteristicAsync(
63 | GattCharacteristicUuids.CurrentTime,
64 | PlainReadNotifyParameters);
65 |
66 | GattLocalCharacteristic currentTimeCharacterisitic = null;
67 | BLEServices.Helpers.GetCharacteristicsFromResult(result, ref currentTimeCharacterisitic);
68 | if (currentTimeCharacterisitic != null)
69 | {
70 | CurrentTime = new BLEServices.CurrentTimeCharacteristic(currentTimeCharacterisitic, this);
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/cs/BLEServices/HeartRateMeasurementCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
8 | using Windows.Devices.Power;
9 | using Windows.Storage.Streams;
10 | using System.Threading;
11 |
12 |
13 | namespace BLE_Hackme.BLEServices
14 | {
15 | public class HeartRateMeasurementCharacteristic : GenericGattCharacteristic
16 | {
17 | private Timer heartRateTicker = null;
18 | public Int16 currentHeartRate = 70;
19 |
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | /// Characteristic this wraps
24 | public HeartRateMeasurementCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
25 | {
26 | heartRateTicker = new Timer(UpdateHeartRate, "", TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
27 | }
28 |
29 | private void UpdateHeartRate(Object state)
30 | {
31 | if (currentHeartRate == 150)
32 | {
33 | currentHeartRate = 70;
34 | }
35 | else
36 | {
37 | currentHeartRate++;
38 | }
39 |
40 | SetHeartRate();
41 | }
42 |
43 | private void SetHeartRate()
44 | {
45 | // Heart rate service starts with flags, then the value. I combine them here then set the characterstic value
46 | byte[] flags = { 0x07 };
47 | byte[] heartRate = BitConverter.GetBytes(currentHeartRate);
48 |
49 | byte[] value = flags.Concat(heartRate).ToArray();
50 |
51 | Value = BLEServices.Helpers.ToIBuffer(value);
52 | NotifyValue();
53 | }
54 |
55 | ///
56 | /// Override so we can update the value before notifying or indicating the client
57 | ///
58 | public override void NotifyValue()
59 | {
60 | base.NotifyValue();
61 | }
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/cs/BLEServices/HeartRateService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
8 |
9 | namespace BLE_Hackme.BLEServices
10 | {
11 | public class HeartRateService : GenericGattService
12 | {
13 | ///
14 | /// Name of the service
15 | ///
16 | public override string Name
17 | {
18 | get
19 | {
20 | return "Heart Rate Service";
21 | }
22 | }
23 |
24 | ///
25 | /// This characteristic is used to send a heart rate measurement.
26 | ///
27 | private HeartRateMeasurementCharacteristic heartRateMeasurement;
28 |
29 | public String randomForDescriptor { get; private set; }
30 |
31 | ///
32 | /// Gets or Sets the heart rate characteristic
33 | ///
34 | public HeartRateMeasurementCharacteristic HeartRateMeasurement
35 | {
36 | get
37 | {
38 | return heartRateMeasurement;
39 | }
40 |
41 | set
42 | {
43 | if (heartRateMeasurement != value)
44 | {
45 | heartRateMeasurement = value;
46 | OnPropertyChanged(new PropertyChangedEventArgs("HeartRateMeasurement"));
47 | }
48 | }
49 | }
50 |
51 | ///
52 | /// Starts the Heart rate service
53 | ///
54 | public override async Task Init()
55 | {
56 | await CreateServiceProvider(GattServiceUuids.HeartRate);
57 |
58 | // Preparing the heart rate characteristics
59 | var heartRateCharacteristicsParameters = PlainReadNotifyParameters;
60 |
61 | //random 4 digits added to manufacturer specific advertisement text
62 | Random rnd = new Random();
63 | randomForDescriptor = Convert.ToString(rnd.Next(1000, 9999));
64 |
65 | heartRateCharacteristicsParameters.UserDescription = $"{Constants.heartRateDescriptorText}{randomForDescriptor}";
66 |
67 | // Create the heart rate characteristic for the service
68 | GattLocalCharacteristicResult result =
69 | await ServiceProvider.Service.CreateCharacteristicAsync(
70 | GattCharacteristicUuids.HeartRateMeasurement,
71 | heartRateCharacteristicsParameters);
72 |
73 | // Grab the characteristic object from the service set it to the HeartRate property which is of a specfic Characteristic type
74 | GattLocalCharacteristic baseHeartRateMeasurement = null;
75 | BLEServices.Helpers.GetCharacteristicsFromResult(result, ref baseHeartRateMeasurement);
76 |
77 | if (baseHeartRateMeasurement != null)
78 | {
79 | HeartRateMeasurement = new BLEServices.HeartRateMeasurementCharacteristic(baseHeartRateMeasurement, this);
80 | }
81 | }
82 |
83 |
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/cs/BLEServices/LightBulbColorCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.Diagnostics;
8 | using System.ComponentModel;
9 | using Windows.Security.Cryptography;
10 |
11 | namespace BLE_Hackme.BLEServices
12 | {
13 | public class LightBulbColorCharacteristic : GenericGattCharacteristic
14 | {
15 | public byte[] pin = { 0, 0, 0 };
16 | public byte[] argb = { 0, 0, 0, 0 };
17 | public byte specialEffectsScenario = 0;
18 |
19 | public LightBulbColorCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
20 | {
21 | // argb
22 | Value = BLEServices.Helpers.ToIBuffer(argb);
23 |
24 | //generate random PIN
25 | Random rnd = new Random();
26 | pin[0] = (byte)rnd.Next(0, 10);
27 | pin[1] = (byte)rnd.Next(0, 10);
28 | pin[2] = (byte)rnd.Next(0, 10);
29 | }
30 |
31 | protected override bool WriteRequested(GattSession session, GattWriteRequest request)
32 | {
33 | byte[] receivedWrite;
34 | CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
35 | var receivedWriteHexString = Helpers.ToHexString(request.Value);
36 |
37 | if ((request.Value.Length != 6) || (receivedWrite[5] != 0xFF))
38 | {
39 | Debug.WriteLine($"Light Bulb color Write requested, INVALID INPUT: {receivedWriteHexString} ({request.Value.Length})");
40 | //send notification to user
41 | OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
42 |
43 | //do not update Value, return
44 | return true;
45 | }
46 |
47 | // ARGB request
48 | if (receivedWrite[0] == 0xAA)
49 | {
50 | ProcessARGB(receivedWrite);
51 | }
52 |
53 | // password protected request
54 | else if (receivedWrite[0] == 0xBE)
55 | {
56 | ProcessPassProtected(receivedWrite);
57 | }
58 |
59 | //send to scenario
60 | return true;
61 | }
62 |
63 | private bool ProcessARGB(byte[] req)
64 | {
65 | // Set the characteristic Value - strip beginning 0xAA and ending 0xFF, leave 4 bytes ARGB
66 | argb = req.Skip(1).Take(4).ToArray();
67 | Value = Helpers.ToIBuffer(argb);
68 | return true;
69 | }
70 |
71 | private bool ProcessPassProtected(byte[] req)
72 | {
73 | //check PIN
74 | if ((req[1] != pin[0]) || (req[2] != pin[1]) || (req[3] != pin[2]))
75 | {
76 | Debug.WriteLine($"Light Bulb protected INVALID PIN: {req[1]}{req[2]}{req[3]}, expected {pin[0]}{pin[1]}{pin[2]}");
77 | OnPropertyChanged(new PropertyChangedEventArgs("InvalidPin"));
78 | return false;
79 | }
80 |
81 | //do not store in the Value, only in the local var
82 | specialEffectsScenario = req[4];
83 | //notify scenario
84 | OnPropertyChanged(new PropertyChangedEventArgs("SpecialValue"));
85 | return true;
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/cs/BLEServices/LightBulbService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.ComponentModel;
8 |
9 |
10 | namespace BLE_Hackme.BLEServices
11 | {
12 | ///
13 | /// Class for Light Bulb Services
14 | ///
15 | public class LightBulbService : GenericGattService
16 | {
17 | ///
18 | /// Name of the service
19 | ///
20 | public override string Name
21 | {
22 | get
23 | {
24 | return "Light Bulb Service";
25 | }
26 | }
27 |
28 | ///
29 | /// Light bulb
30 | ///
31 | private LightBulbSwitchCharacteristic lightBulbSwitch;
32 | private LightBulbTTSCharacteristic lightBulbTTS;
33 | private LightBulbColorCharacteristic lightBulbColor;
34 |
35 | ///
36 | /// Gets or sets the light bulb state
37 | ///
38 | public LightBulbSwitchCharacteristic LightBulbSwitch
39 | {
40 | get
41 | {
42 | return lightBulbSwitch;
43 | }
44 |
45 | set
46 | {
47 | if (lightBulbSwitch != value)
48 | {
49 | lightBulbSwitch = value;
50 | OnPropertyChanged(new PropertyChangedEventArgs("LightBulbSwitch"));
51 | }
52 | }
53 | }
54 | public LightBulbTTSCharacteristic LightBulbTTS
55 | {
56 | get
57 | {
58 | return lightBulbTTS;
59 | }
60 |
61 | set
62 | {
63 | if (lightBulbTTS != value)
64 | {
65 | lightBulbTTS = value;
66 | OnPropertyChanged(new PropertyChangedEventArgs("LightBulbTTS"));
67 | }
68 | }
69 | }
70 |
71 | ///
72 | /// Gets or sets the lightbulb color
73 | ///
74 | public LightBulbColorCharacteristic LightBulbColor
75 | {
76 | get
77 | {
78 | return lightBulbColor;
79 | }
80 |
81 | set
82 | {
83 | if (lightBulbColor != value)
84 | {
85 | lightBulbColor = value;
86 | OnPropertyChanged(new PropertyChangedEventArgs("LightBulbColor"));
87 | }
88 | }
89 | }
90 |
91 |
92 | ///
93 | /// Asynchronous initialization
94 | ///
95 | /// Initialization Task
96 | public override async Task Init()
97 | {
98 | await CreateServiceProvider(Constants.LightBulbServiceUuid);
99 |
100 | //Light Bulb Switch characteristic
101 | GattLocalCharacteristicParameters lightBulbSwitchCharacteristicsParameters = PlainReadWriteParameters;
102 | // Set the user descriptions
103 | lightBulbSwitchCharacteristicsParameters.UserDescription = "Light bulb on/off";
104 | // Create the characteristic for the service
105 | GattLocalCharacteristicResult result =
106 | await ServiceProvider.Service.CreateCharacteristicAsync(
107 | Constants.LightBulbSwitchCharacteristicUuid,
108 | lightBulbSwitchCharacteristicsParameters);
109 |
110 | // Grab the characterist object from the service set it to the property which is of a specfic Characteristic type
111 | GattLocalCharacteristic baseLightBulbSwitch = null;
112 | BLEServices.Helpers.GetCharacteristicsFromResult(result, ref baseLightBulbSwitch);
113 |
114 | if (baseLightBulbSwitch != null)
115 | {
116 | LightBulbSwitch = new BLEServices.LightBulbSwitchCharacteristic(baseLightBulbSwitch, this);
117 | }
118 |
119 |
120 |
121 | //Light Bulb Text To Speech characteristic
122 | GattLocalCharacteristicParameters lightBulbTTSCharacteristicsParameters = PlainWriteOrWriteWithoutResponseParameters;
123 | // Set the user descriptions
124 | lightBulbTTSCharacteristicsParameters.UserDescription = "Light bulb text to speech";
125 | // Create the characteristic for the service
126 | result =
127 | await ServiceProvider.Service.CreateCharacteristicAsync(
128 | Constants.LightBulbTTSCharacteristicUuid,
129 | lightBulbTTSCharacteristicsParameters);
130 |
131 | // Grab the characterist object from the service set it to the property which is of a specfic Characteristic type
132 | GattLocalCharacteristic baseLightBulbTTS = null;
133 | BLEServices.Helpers.GetCharacteristicsFromResult(result, ref baseLightBulbTTS);
134 |
135 | if (baseLightBulbTTS != null)
136 | {
137 | LightBulbTTS = new BLEServices.LightBulbTTSCharacteristic(baseLightBulbTTS, this);
138 | }
139 |
140 |
141 |
142 |
143 | //Light Bulb Color characteristic
144 | GattLocalCharacteristicParameters lightBulbColorCharacteristicsParameters = PlainWriteOrWriteWithoutResponseParameters;
145 | // Set the user descriptions
146 | lightBulbColorCharacteristicsParameters.UserDescription = "Light bulb color/dim";
147 | // Create the characteristic for the service
148 | result =
149 | await ServiceProvider.Service.CreateCharacteristicAsync(
150 | Constants.LightBulbColorCharacteristicUuid,
151 | lightBulbColorCharacteristicsParameters);
152 |
153 | // Grab the characterist object from the service set it to the property which is of a specfic Characteristic type
154 | GattLocalCharacteristic baseLightBulbColor = null;
155 | BLEServices.Helpers.GetCharacteristicsFromResult(result, ref baseLightBulbColor);
156 |
157 | if (baseLightBulbColor != null)
158 | {
159 | LightBulbColor = new BLEServices.LightBulbColorCharacteristic(baseLightBulbColor, this);
160 | }
161 |
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/cs/BLEServices/LightBulbSwitchCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.Diagnostics;
8 | using System.ComponentModel;
9 |
10 |
11 | namespace BLE_Hackme.BLEServices
12 | {
13 | ///
14 | /// Implementation of the light bulb switch
15 | ///
16 | public class LightBulbSwitchCharacteristic : GenericGattCharacteristic
17 | {
18 |
19 | private DateTime previousTime, currentTime;
20 | private TimeSpan span;
21 | private int switchCounter;
22 |
23 |
24 | public LightBulbSwitchCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
25 | {
26 | Value = BLEServices.Helpers.ToIBuffer((byte)0);
27 | switchCounter = 0;
28 |
29 | }
30 |
31 | protected override bool WriteRequested(GattSession session, GattWriteRequest request)
32 | {
33 |
34 | var receivedWrite = Helpers.ToHexString(request.Value);
35 |
36 | // invalid input, discard
37 | if ( !receivedWrite.Equals("00") && !receivedWrite.Equals("01") )
38 | {
39 | Debug.WriteLine($"Light Bulb cmd WriteRequested: INVALID INPUT: {receivedWrite} ({request.Value.Length})");
40 | //send notification to user
41 | OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
42 | //do not update Value, return
43 | return true;
44 | }
45 |
46 | //check for macros blink challenge
47 | currentTime = DateTime.Now;
48 | span = currentTime.Subtract(previousTime);
49 | Debug.WriteLine($"Time span from previoius write: {span.TotalMilliseconds} ms");
50 | previousTime = currentTime;
51 | // previus write less than 0.5s ago
52 | if (span.TotalMilliseconds < 500)
53 | {
54 | Debug.WriteLine("Time span less than 0.5s!");
55 | //check if previous value != current (light bulb swith)
56 | if (Value != request.Value)
57 | {
58 | switchCounter++;
59 | Debug.WriteLine($"Value switch - OK {switchCounter}");
60 | } else
61 | {
62 | switchCounter = 0;
63 | }
64 | }
65 |
66 | if (switchCounter > 10)
67 | {
68 | OnPropertyChanged(new PropertyChangedEventArgs("BlinkPassed"));
69 | }
70 |
71 | // Set the characteristic Value
72 | Value = request.Value;
73 |
74 | return true;
75 | }
76 |
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/cs/BLEServices/LightBulbTTSCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.Diagnostics;
8 | using Windows.Security.Cryptography;
9 | using Windows.Devices.SerialCommunication;
10 | using System.ComponentModel;
11 |
12 | namespace BLE_Hackme.BLEServices
13 | {
14 |
15 | public class LightBulbTTSCharacteristic : GenericGattCharacteristic
16 | {
17 |
18 | public LightBulbTTSCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
19 | {
20 | Value = BLEServices.Helpers.ToIBuffer(0);
21 | }
22 |
23 | protected override bool WriteRequested(GattSession session, GattWriteRequest request)
24 | {
25 | //check if this is write command not write request
26 | if (request.Option == GattWriteOption.WriteWithResponse)
27 | {
28 | OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
29 | Debug.WriteLine("Write request");
30 | }
31 | else
32 | {
33 | Debug.WriteLine("Write command");
34 | Value = request.Value;
35 | }
36 | return true;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/cs/BLEServices/QuickLockAuthCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
8 | using System.Diagnostics;
9 | using System.Runtime.InteropServices.WindowsRuntime;
10 | using Windows.Security.Cryptography;
11 |
12 | namespace BLE_Hackme.BLEServices
13 | {
14 | public class QuickLockAuthCharacteristic : GenericGattCharacteristic
15 | {
16 | // matching sample pcap dump
17 | public byte[] password = { 0x66, 0x61, 0x26, 0x66 };
18 |
19 | public QuickLockAuthCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
20 | {
21 | Value = BLEServices.Helpers.ToIBuffer((byte)0);
22 | }
23 |
24 | protected override bool WriteRequested(GattSession session, GattWriteRequest request)
25 | {
26 | byte[] receivedWrite;
27 | CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
28 | var receivedWriteHexString = Helpers.ToHexString(request.Value);
29 |
30 | QuickLockMainService parent = (QuickLockMainService)this.ParentService;
31 |
32 | //expected: 0066612666 (pcap), or 006661266600000000 (also correct)
33 | if ( (request.Value.Length != 5) && (request.Value.Length != 9))
34 | {
35 | Debug.WriteLine($"Smart lock auth WriteRequested, but invalid format: {receivedWriteHexString} ({request.Value.Length})");
36 | //do not update Value, return
37 | OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
38 | return true;
39 | }
40 |
41 | //check just the first byte and password, ignore rest if provided
42 | if ((receivedWrite[0] != 0x00) || (receivedWrite[1] != password[0]) || (receivedWrite[2] != password[1]) || (receivedWrite[3] != password[2]) || (receivedWrite[4] != password[3]))
43 | {
44 | Debug.WriteLine($"Smart lock auth WriteRequested: INVALID PASSWORD: {receivedWriteHexString} ({request.Value.Length})");
45 | //do not update Value, return
46 | OnPropertyChanged(new PropertyChangedEventArgs("InvalidPin"));
47 | return true;
48 | }
49 |
50 | parent.UpdateAuthenticationState(true);
51 | OnPropertyChanged(new PropertyChangedEventArgs("AuthenticationState"));
52 |
53 | return true;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/cs/BLEServices/QuickLockAuthStatusCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
8 | using System.Diagnostics;
9 | using System.Runtime.InteropServices.WindowsRuntime;
10 | using Windows.Security.Cryptography;
11 |
12 | namespace BLE_Hackme.BLEServices
13 | {
14 | public class QuickLockAuthStatusCharacteristic : GenericGattCharacteristic
15 | {
16 | public QuickLockAuthStatusCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
17 | {
18 |
19 | Value = BLEServices.Helpers.ToIBuffer((byte)0);
20 | }
21 |
22 | // the value is updated from the QuickLockAuthCharacteristic
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/cs/BLEServices/QuickLockCommandCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.Diagnostics;
8 | using System.Runtime.InteropServices.WindowsRuntime;
9 | using Windows.Security.Cryptography;
10 | using System.ComponentModel;
11 |
12 | namespace BLE_Hackme.BLEServices
13 | {
14 | public class QuickLockCommandCharacteristic : GenericGattCharacteristic
15 | {
16 | public QuickLockCommandCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
17 | {
18 | Value = BLEServices.Helpers.ToIBuffer((byte)0);
19 | }
20 |
21 | protected override bool WriteRequested(GattSession session, GattWriteRequest request)
22 | {
23 | byte[] receivedWrite;
24 | CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
25 | var receivedWriteHexString = Helpers.ToHexString(request.Value);
26 |
27 | QuickLockMainService parent = (QuickLockMainService)this.ParentService;
28 |
29 | if (!parent.isAuthenticated)
30 | {
31 | Debug.WriteLine($"Quicklock cmd WriteRequested, but not authenticated {receivedWriteHexString} ({request.Value.Length})");
32 | //do not update Value, return
33 | OnPropertyChanged(new PropertyChangedEventArgs("Unauthenticated"));
34 | return true;
35 | }
36 |
37 | if ((request.Value.Length != 1) || ( (receivedWrite[0] != 0x00) && (receivedWrite[0] !=0x01)) )
38 | {
39 | Debug.WriteLine($"Quicklock cmd WriteRequested, but invalid format {receivedWriteHexString} ({request.Value.Length})");
40 | //do not update Value, return
41 | OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
42 | return true;
43 | }
44 |
45 | Debug.WriteLine($"Quicklock cmd received: {receivedWriteHexString} ({request.Value.Length})");
46 |
47 | if (receivedWrite[0] == 00) // lock
48 | {
49 | Debug.WriteLine($"Locking!");
50 | parent.UpdateUnlockState(false);
51 | }
52 | else if (receivedWrite[0] == 01) // unlock
53 | {
54 | Debug.WriteLine($"Unlocking!");
55 | parent.UpdateUnlockState(true);
56 | }
57 |
58 | OnPropertyChanged(new PropertyChangedEventArgs("LockState"));
59 |
60 | return true;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/cs/BLEServices/QuickLockHistoryControlCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.Diagnostics;
8 | using System.Runtime.InteropServices.WindowsRuntime;
9 | using Windows.Security.Cryptography;
10 | using System.ComponentModel;
11 |
12 | namespace BLE_Hackme.BLEServices
13 | {
14 | public class QuickLockHistoryControlCharacteristic : GenericGattCharacteristic
15 | {
16 | public QuickLockHistoryControlCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
17 | {
18 | Value = Helpers.ToIBuffer((byte)1);
19 | }
20 |
21 | // if received "01", send logs via notification from HistoryData characteristic
22 | protected override bool WriteRequested(GattSession session, GattWriteRequest request)
23 | {
24 | byte[] receivedWrite;
25 | CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
26 | var receivedWriteHexString = Helpers.ToHexString(request.Value);
27 |
28 | QuickLockHistoryService parent = (QuickLockHistoryService)this.ParentService;
29 |
30 | if ((request.Value.Length != 1) || (receivedWrite[0] != 0x01))
31 | {
32 | Debug.WriteLine($"Quicklock history cmd WriteRequested, but invalid format: {receivedWriteHexString} ({request.Value.Length})");
33 | //do not update Value, return
34 | OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
35 | return true;
36 | }
37 |
38 | Debug.WriteLine($"Quicklock history cmd received, sending out logs");
39 |
40 | // OnPropertyChanged(new PropertyChangedEventArgs("Logs"));
41 |
42 | // set the status characteristic and send notification
43 | parent.QuickLockHistoryData.SendLogs();
44 |
45 | return true;
46 | }
47 |
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/cs/BLEServices/QuickLockHistoryDataCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.Diagnostics;
8 | using System.Runtime.InteropServices.WindowsRuntime;
9 | using Windows.Security.Cryptography;
10 | using System.ComponentModel;
11 |
12 | namespace BLE_Hackme.BLEServices
13 | {
14 | public class QuickLockHistoryDataCharacteristic : GenericGattCharacteristic
15 | {
16 |
17 | private static String LOG_END_DELIMITER = "E0E0E0E0E0E0E0E0000000000000000000000000";
18 |
19 | // for now just a few static log history values
20 | private static String[] SAMPLE_LOGS =
21 | {
22 | // user "smartlockpick" 2020-11-06 10:56:38
23 | "0d736d6172746c6f636b7069636b0066e8372700",
24 | // user "smartlockpick" 2020-11-06 13:40:00
25 | "0d736d6172746c6f636b7069636b00b00e382700",
26 | // user "hackmeuser" 2020-11-07 13:30
27 | "0a6861636b6d657573657200000000fc5d392700",
28 | };
29 |
30 | public QuickLockHistoryDataCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
31 | {
32 | Value = Helpers.HexStringToIBuffer(LOG_END_DELIMITER);
33 | }
34 |
35 | public async void SendLogs()
36 | {
37 | // send all the SAMPLE_LOGS
38 | foreach (String log in SAMPLE_LOGS)
39 | {
40 | Debug.WriteLine($"Sending log notification: {log}");
41 | Value = BLEServices.Helpers.HexStringToIBuffer(log);
42 | // short delay to imitate real device, and also allow to notice in nRF that the value is changing
43 | await Task.Delay(200);
44 | base.NotifyValue();
45 | }
46 |
47 | Debug.WriteLine($"Sending log notification end delimiter: {LOG_END_DELIMITER}");
48 | Value = BLEServices.Helpers.HexStringToIBuffer(LOG_END_DELIMITER);
49 | base.NotifyValue();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/cs/BLEServices/QuickLockHistoryService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.ComponentModel;
8 |
9 | namespace BLE_Hackme.BLEServices
10 | {
11 | public class QuickLockHistoryService : GenericGattService
12 | {
13 |
14 | // 0 - uninitialized, 1 - init, waiting for auth, 2 - authenticated
15 | public byte currentState = 0;
16 | // 0 - locked, 1 - unlocked
17 | public byte locked = 0;
18 |
19 | ///
20 | /// Name of the service
21 | ///
22 | public override string Name
23 | {
24 | get
25 | {
26 | return "Quick Lock History Service";
27 | }
28 | }
29 |
30 | private QuickLockHistoryControlCharacteristic quickLockHistoryControl;
31 | private QuickLockHistoryDataCharacteristic quickLockHistoryData;
32 | private QuickLockUsernameCharacteristic quickLockUsername;
33 |
34 | ///
35 | /// Getters / setters
36 | ///
37 |
38 | public QuickLockHistoryControlCharacteristic QuickLockHistoryControl
39 | {
40 | get
41 | {
42 | return quickLockHistoryControl;
43 | }
44 | set
45 | {
46 | if (quickLockHistoryControl != value)
47 | {
48 | quickLockHistoryControl = value;
49 | OnPropertyChanged(new PropertyChangedEventArgs("QuickLockHistoryControl"));
50 | }
51 | }
52 | }
53 |
54 | public QuickLockHistoryDataCharacteristic QuickLockHistoryData
55 | {
56 | get
57 | {
58 | return quickLockHistoryData;
59 | }
60 | set
61 | {
62 | if (quickLockHistoryData != value)
63 | {
64 | quickLockHistoryData = value;
65 | OnPropertyChanged(new PropertyChangedEventArgs("QuickLockHistory"));
66 | }
67 | }
68 | }
69 |
70 | public QuickLockUsernameCharacteristic QuickLockUsername
71 | {
72 | get
73 | {
74 | return quickLockUsername;
75 | }
76 | set
77 | {
78 | if (quickLockUsername != value)
79 | {
80 | quickLockUsername = value;
81 | OnPropertyChanged(new PropertyChangedEventArgs("QuickLockUsername"));
82 | }
83 | }
84 | }
85 |
86 |
87 | ///
88 | /// Asynchronous initialization
89 | ///
90 | /// Initialization Task
91 | public override async Task Init()
92 | {
93 | await CreateServiceProvider(Constants.QuickLockHistoryServiceUuid);
94 |
95 |
96 | // history control
97 |
98 | GattLocalCharacteristicParameters quickLockHistoryControlCharacteristicsParameters = PlainReadWriteParameters;
99 | // Set the user descriptions
100 | quickLockHistoryControlCharacteristicsParameters.UserDescription = "control!";
101 |
102 | // Create the characteristic for the service
103 | GattLocalCharacteristicResult result =
104 | await ServiceProvider.Service.CreateCharacteristicAsync(
105 | Constants.QuickLockHistoryControlCharacteristicUuid,
106 | quickLockHistoryControlCharacteristicsParameters);
107 |
108 | // Grab the characteristic object from the service set it to the property which is of a specfic Characteristic type
109 | GattLocalCharacteristic baseQuickLockHistoryControl = null;
110 | BLEServices.Helpers.GetCharacteristicsFromResult(result, ref baseQuickLockHistoryControl);
111 |
112 | if (baseQuickLockHistoryControl != null)
113 | {
114 | QuickLockHistoryControl = new BLEServices.QuickLockHistoryControlCharacteristic(baseQuickLockHistoryControl, this);
115 | }
116 |
117 |
118 | // history data
119 |
120 | GattLocalCharacteristicParameters quickLockHistoryDataCharacteristicsParameters = PlainReadNotifyParameters;
121 | // Set the user descriptions
122 | quickLockHistoryDataCharacteristicsParameters.UserDescription = "history!";
123 |
124 | // Create the characteristic for the service
125 | result =
126 | await ServiceProvider.Service.CreateCharacteristicAsync(
127 | Constants.QuickLockHistoryDataCharacteristicUuid,
128 | quickLockHistoryDataCharacteristicsParameters);
129 |
130 | // Grab the characteristic object from the service set it to the property which is of a specfic Characteristic type
131 | GattLocalCharacteristic baseQuickLockHistoryData = null;
132 | BLEServices.Helpers.GetCharacteristicsFromResult(result, ref baseQuickLockHistoryData);
133 |
134 | if (baseQuickLockHistoryData != null)
135 | {
136 | QuickLockHistoryData = new BLEServices.QuickLockHistoryDataCharacteristic(baseQuickLockHistoryData, this);
137 | }
138 |
139 |
140 | // "imei" (username)
141 |
142 | // Preparing the characteristics
143 | GattLocalCharacteristicParameters quickLockUsernameCharacteristicsParameters = PlainReadWriteParameters;
144 | // Set the user descriptions
145 | quickLockUsernameCharacteristicsParameters.UserDescription = "phone id!";
146 |
147 | // Create the characteristic for the service
148 | result =
149 | await ServiceProvider.Service.CreateCharacteristicAsync(
150 | Constants.QuickLockUsernameCharacteristicUuid,
151 | quickLockUsernameCharacteristicsParameters);
152 |
153 | // Grab the characterist object from the service set it to the property which is of a specfic Characteristic type
154 | GattLocalCharacteristic baseQuickLockUsername = null;
155 | BLEServices.Helpers.GetCharacteristicsFromResult(result, ref baseQuickLockUsername);
156 |
157 | if (baseQuickLockUsername != null)
158 | {
159 | QuickLockUsername = new BLEServices.QuickLockUsernameCharacteristic(baseQuickLockUsername, this);
160 | }
161 |
162 | }
163 | }
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/cs/BLEServices/QuickLockOpenTimeCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
8 | using System.Diagnostics;
9 | using System.Runtime.InteropServices.WindowsRuntime;
10 | using Windows.Security.Cryptography;
11 |
12 | namespace BLE_Hackme.BLEServices
13 | {
14 | // this characteristic stores number of seconds the lock stays unlocked (before auto-lock again)
15 | public class QuickLockOpenTimeCharacteristic : GenericGattCharacteristic
16 | {
17 | public QuickLockOpenTimeCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
18 | {
19 | // for now just static 5 seconds, setting the value not yet implemented in HackMe
20 | Value = BLEServices.Helpers.ToIBuffer((byte)5);
21 | }
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/cs/BLEServices/QuickLockUnlockStatusCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
8 | using System.Diagnostics;
9 | using System.Runtime.InteropServices.WindowsRuntime;
10 | using Windows.Security.Cryptography;
11 |
12 | namespace BLE_Hackme.BLEServices
13 | {
14 | public class QuickLockUnlockStatusCharacteristic : GenericGattCharacteristic
15 | {
16 | public QuickLockUnlockStatusCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
17 | {
18 |
19 | Value = BLEServices.Helpers.ToIBuffer((byte)0);
20 | }
21 |
22 | // the value is actually updated from the QuickLockCommandCharacteristic
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/cs/BLEServices/QuickLockUsernameCharacteristic.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
7 | using System.Diagnostics;
8 | using System.Runtime.InteropServices.WindowsRuntime;
9 | using Windows.Security.Cryptography;
10 | using System.ComponentModel;
11 |
12 | namespace BLE_Hackme.BLEServices
13 | {
14 | public class QuickLockUsernameCharacteristic : GenericGattCharacteristic
15 | {
16 |
17 | public QuickLockUsernameCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
18 | {
19 | // "smartlockpick" user
20 | Value = Helpers.HexStringToIBuffer("0d736d6172746c6f636b7069636b00");
21 | }
22 |
23 | protected override bool WriteRequested(GattSession session, GattWriteRequest request)
24 | {
25 | byte[] receivedWrite;
26 | CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
27 | var receivedWriteHexString = Helpers.ToHexString(request.Value);
28 |
29 | // valid format: one byte of length, followed by ascii hex username, and padded with 00 up to 15 bytes
30 | // for now just check the length and accept 15 chars only
31 | if ( (request.Value.Length != 15) )
32 | {
33 | Debug.WriteLine($"Quicklock username WriteRequested, wrong length: {receivedWriteHexString} ({request.Value.Length})");
34 | //do not update Value, return
35 | OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
36 | return true;
37 | }
38 |
39 | // Set the characteristic Value to the value received
40 | Value = request.Value;
41 | return true;
42 | }
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/cs/BLEServices/iBeacon.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Windows.Storage.Streams;
7 |
8 | namespace BLE_Hackme.BLEServices
9 | {
10 | class iBeacon
11 | {
12 | public Guid Uuid { get; private set; }
13 | public ushort Major { get; private set; }
14 | public ushort Minor { get; private set; }
15 | public byte RSSI { get; private set; }
16 |
17 | public iBeacon(Guid uuid, ushort major, ushort minor, byte rssi)
18 | {
19 | Uuid = uuid;
20 | Major = major;
21 | Minor = minor;
22 | RSSI = rssi;
23 | }
24 |
25 | public IBuffer getBuffer()
26 | {
27 | var writer = new DataWriter();
28 |
29 | writer.WriteByte(0x02); // type: 0x02 = iBeacon
30 | writer.WriteByte(0x15); // length 21 bytes
31 |
32 | writer.WriteBytes(Uuid.ToByteArray());
33 | writer.WriteUInt16(Major);
34 | writer.WriteUInt16(Minor);
35 | writer.WriteByte(RSSI);
36 |
37 | return writer.DetachBuffer();
38 | }
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/cs/BLE_Hackme.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30523.141
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BLE_Hackme", "BLE_Hackme.csproj", "{445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|ARM = Debug|ARM
12 | Debug|x64 = Debug|x64
13 | Debug|x86 = Debug|x86
14 | Release|Any CPU = Release|Any CPU
15 | Release|ARM = Release|ARM
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|Any CPU.ActiveCfg = Debug|x86
21 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|Any CPU.Build.0 = Debug|x86
22 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|Any CPU.Deploy.0 = Debug|x86
23 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|ARM.ActiveCfg = Debug|ARM
24 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|ARM.Build.0 = Debug|ARM
25 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|ARM.Deploy.0 = Debug|ARM
26 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|x64.ActiveCfg = Debug|x64
27 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|x64.Build.0 = Debug|x64
28 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|x64.Deploy.0 = Debug|x64
29 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|x86.ActiveCfg = Debug|x86
30 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|x86.Build.0 = Debug|x86
31 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Debug|x86.Deploy.0 = Debug|x86
32 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|Any CPU.ActiveCfg = Release|x86
33 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|Any CPU.Build.0 = Release|x86
34 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|Any CPU.Deploy.0 = Release|x86
35 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|ARM.ActiveCfg = Release|ARM
36 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|ARM.Build.0 = Release|ARM
37 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|ARM.Deploy.0 = Release|ARM
38 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|x64.ActiveCfg = Release|x64
39 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|x64.Build.0 = Release|x64
40 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|x64.Deploy.0 = Release|x64
41 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|x86.ActiveCfg = Release|x86
42 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|x86.Build.0 = Release|x86
43 | {445C51F0-1B60-5DF7-8798-DC8C1F7D0C90}.Release|x86.Deploy.0 = Release|x86
44 | EndGlobalSection
45 | GlobalSection(SolutionProperties) = preSolution
46 | HideSolutionNode = FALSE
47 | EndGlobalSection
48 | GlobalSection(ExtensibilityGlobals) = postSolution
49 | SolutionGuid = {8F332316-09D2-4B99-B63F-86A5C07FE034}
50 | EndGlobalSection
51 | EndGlobal
52 |
--------------------------------------------------------------------------------
/cs/Constants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
3 |
4 | namespace BLE_Hackme
5 | {
6 | public class Constants
7 | {
8 | public static readonly Guid iBeaconUuid = Guid.Parse("6834636b-6d33-6942-3334-63306e553144");
9 |
10 | public static readonly String manufacturerSpecificAdvertisementText = "Please don't hack me ";
11 |
12 | public static readonly String heartRateDescriptorText = "Beats per minute ";
13 |
14 | public static readonly Guid LightBulbServiceUuid = Guid.Parse("6834636b-6d33-4c31-3668-744275314221");
15 |
16 | public static readonly Guid LightBulbSwitchCharacteristicUuid = Guid.Parse("6834636b-6d33-4c31-3668-744275314201");
17 | public static readonly Guid LightBulbTTSCharacteristicUuid = Guid.Parse("6834636b-6d33-4c31-3668-744275314202");
18 | public static readonly Guid LightBulbColorCharacteristicUuid = Guid.Parse("6834636b-6d33-4c31-3668-744275314203");
19 | public static readonly Guid LightBulbProtectedCharacteristicUuid = Guid.Parse("6834636b-6d33-4c31-3668-744275314204");
20 |
21 | //quicklock
22 | public static readonly Guid QuickLockHistoryServiceUuid = Guid.Parse("0000fff0-0000-1000-8000-00805f9b34fb");
23 | public static readonly Guid QuickLockHistoryControlCharacteristicUuid = Guid.Parse("0000fff1-0000-1000-8000-00805f9b34fb");
24 | public static readonly Guid QuickLockHistoryDataCharacteristicUuid = Guid.Parse("0000fff2-0000-1000-8000-00805f9b34fb");
25 | public static readonly Guid QuickLockUsernameCharacteristicUuid = Guid.Parse("0000fff3-0000-1000-8000-00805f9b34fb");
26 |
27 | public static readonly Guid QuickLockMainServiceUuid = Guid.Parse("0000ffd0-0000-1000-8000-00805f9b34fb");
28 | public static readonly Guid QuickLockAuthCharacteristicUuid = Guid.Parse("0000ffd6-0000-1000-8000-00805f9b34fb");
29 | public static readonly Guid QuickLockAuthStatusCharacteristicUuid = Guid.Parse("0000ffd7-0000-1000-8000-00805f9b34fb");
30 | public static readonly Guid QuickLockOpenTimeCharacteristicUuid = Guid.Parse("0000ffd8-0000-1000-8000-00805f9b34fb");
31 | public static readonly Guid QuickLockCommandCharacteristicUuid = Guid.Parse("0000ffd9-0000-1000-8000-00805f9b34fb");
32 | public static readonly Guid QuickLockUnlockStatusCharacteristicUuid = Guid.Parse("0000ffda-0000-1000-8000-00805f9b34fb");
33 |
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/cs/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/cs/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | BLE HackMe
18 | smartlockpicking.com
19 | Assets\StoreLogo-sdk.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
33 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/cs/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/cs/Properties/AssemblyInfo.cs
--------------------------------------------------------------------------------
/cs/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_01_Compatibility.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Hello and welcome to Bluetooth Low Energy hardware-less hackme!
17 |
18 |
19 | The project aims to introduce the BLE protocol and its security basics.
20 | Your computer with Bluetooth interface will simulate various BLE devices - on the radio layer working exactly as real ones.
21 | In a series of tasks you will get familiar with BLE advertisements, beacons, connections, services and characteristics.
22 | This initial knowledge will allow for further research and security analysis of various Bluetooth devices.
23 |
24 |
25 | For solving the tasks you will need Android phone (iOS has limited low level BLE features).
26 | It is also possible to use other BLE tools, for example running on Linux,
27 | however details are not covered here and you are on your own.
28 |
29 |
30 | In a rare case when your Windows system is "N" edition (for example Windows Professional N), it comes without a media pack, required for a few tasks.
31 | Please install "Microsoft Media Feature Pack".
32 | If your system has Windows Media Player available (standard), you are good to go.
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | Checking your system compatibility and starting BLE services...
47 |
48 |
49 | If it takes too long, try to:
50 |
51 |
52 | - turn your Bluetooth interface off and on again
53 |
54 |
55 | - restart this application
56 |
57 |
58 | - restart your system
59 |
60 |
61 | - use a different computer
62 |
63 |
64 | For more troubleshooting see also
65 | FAQ.
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Hooray, looks like your device is supported!
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | Sorry, there is no Bluetooth adapter, or the default Bluetooth adapter cannot act as a Bluetooth server.
90 | You can try to:
91 |
92 |
93 | - turn your Bluetooth interface off and on again
94 |
95 |
96 | - restart this application
97 |
98 |
99 | - restart your system
100 |
101 |
102 | - use a different computer
103 |
104 |
105 | For more troubleshooting see also
106 | FAQ .
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_01_Compatibility.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using System.Threading.Tasks;
15 | using Windows.Storage.Streams;
16 | using Windows.UI.Xaml.Navigation;
17 | using Windows.Devices.Bluetooth;
18 | using Windows.Devices.Bluetooth.GenericAttributeProfile;
19 | using System.Diagnostics;
20 |
21 |
22 | namespace BLE_Hackme
23 | {
24 | public sealed partial class Scenario_01_Compatibility : Page
25 | {
26 |
27 | private MainPage rootPage = MainPage.Current;
28 |
29 | public Scenario_01_Compatibility()
30 | {
31 | this.InitializeComponent();
32 | }
33 |
34 | protected override async void OnNavigatedTo(NavigationEventArgs e)
35 | {
36 | var supported = await rootPage.Ble.CheckPeripheralRoleSupportAsync();
37 |
38 | if (supported)
39 | {
40 | var started = await rootPage.Ble.AdvertisingForScenario(this.GetType().Name);
41 |
42 | if (started)
43 | {
44 | Checking.Visibility = Visibility.Collapsed;
45 | Success.Visibility = Visibility.Visible;
46 | rootPage.NotifyUser("BLE device simulation successfully started!", NotifyType.StatusMessage);
47 | rootPage.ScenariosEnable();
48 | }
49 | else // supported but starting error
50 | {
51 | Checking.Visibility = Visibility.Collapsed;
52 | ErrorStarting.Visibility = Visibility.Visible;
53 | rootPage.NotifyUser("Error starting BLE device simulation...", NotifyType.ErrorMessage);
54 | }
55 | }
56 | else //not supported, display error message
57 | {
58 | Checking.Visibility = Visibility.Collapsed;
59 | ErrorStarting.Visibility = Visibility.Visible;
60 | rootPage.NotifyUser("Bluetooth device unsupported...", NotifyType.ErrorMessage);
61 |
62 | }
63 | }
64 |
65 | }
66 | }
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_02_Intro.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using Windows.Storage.Streams;
16 | using Windows.Devices.Bluetooth.Advertisement;
17 | using Windows.Networking;
18 | using Windows.Networking.Connectivity;
19 | using System.Diagnostics;
20 |
21 | namespace BLE_Hackme
22 | {
23 | public sealed partial class Scenario_02_Intro : Page
24 | {
25 | private MainPage rootPage = MainPage.Current;
26 | private String hostName;
27 | private String scenarioName;
28 |
29 | public Scenario_02_Intro()
30 | {
31 | this.InitializeComponent();
32 | hostName = GetHostName();
33 | scenarioName = this.GetType().Name;
34 | }
35 |
36 | protected override async void OnNavigatedTo(NavigationEventArgs e)
37 | {
38 | Debug.WriteLine($"Hostname: {hostName}");
39 | DeviceName.Text = hostName;
40 |
41 | // set up BLE advertising for this scenario
42 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
43 |
44 | if (ret == false || rootPage.Ble.lightBulbService == null)
45 | {
46 | Debug.WriteLine("Error, lightbulb service is null!");
47 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
48 | }
49 |
50 | if (rootPage.isSolved.ContainsKey(scenarioName))
51 | {
52 | if (rootPage.isSolved[scenarioName] == true)
53 | {
54 | Solved.Visibility = Visibility.Visible;
55 | }
56 | }
57 | }
58 | private String GetHostName()
59 | {
60 | var hostNames = NetworkInformation.GetHostNames();
61 | var hostName = hostNames.FirstOrDefault(name => name.Type == HostNameType.DomainName)?.DisplayName ?? "???";
62 | hostName = hostName.ToUpper();
63 |
64 | // remove everything after "." (optional domain name)
65 | int index = hostName.IndexOf(".");
66 | if (index > 0)
67 | hostName = hostName.Substring(0, index);
68 |
69 | if (hostName.Length > 15)
70 | {
71 | hostName = hostName.Substring(0, 15);
72 | }
73 | return hostName;
74 | }
75 |
76 |
77 | private void ValueSubmitButton_Click()
78 | {
79 | if ( ValueToEnter.Text.Equals(hostName, StringComparison.CurrentCultureIgnoreCase))
80 | {
81 | rootPage.NotifyCorrect(scenarioName);
82 | Solved.Visibility = Visibility.Visible;
83 | }
84 | else
85 | {
86 | rootPage.NotifyUser("Sorry, incorrect, try again!", NotifyType.ErrorMessage);
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_03_Advertisements.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using Windows.Storage.Streams;
16 | using Windows.Devices.Bluetooth.Advertisement;
17 | using System.Diagnostics;
18 |
19 |
20 | namespace BLE_Hackme
21 | {
22 | public sealed partial class Scenario_03_Advertisements : Page
23 | {
24 | private MainPage rootPage = MainPage.Current;
25 | private String scenarioName;
26 |
27 | public Scenario_03_Advertisements()
28 | {
29 | this.InitializeComponent();
30 | scenarioName = this.GetType().Name;
31 | }
32 |
33 | protected override async void OnNavigatedTo(NavigationEventArgs e)
34 | {
35 | // set up BLE advertising for this scenario
36 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
37 |
38 | if (ret == false || rootPage.Ble.lightBulbService == null)
39 | {
40 | Debug.WriteLine("Error, lightbulb service is null!");
41 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
42 | }
43 |
44 | if (rootPage.isSolved.ContainsKey(scenarioName))
45 | {
46 | if (rootPage.isSolved[scenarioName] == true)
47 | {
48 | Solved.Visibility = Visibility.Visible;
49 | }
50 | }
51 | }
52 |
53 | private void ValueSubmitButton_Click()
54 | {
55 | if ( ValueToEnter.Text.Equals("0x0A180F18", StringComparison.CurrentCultureIgnoreCase) || ValueToEnter.Text.Equals("0A180F18", StringComparison.CurrentCultureIgnoreCase) )
56 | {
57 | rootPage.NotifyCorrect(scenarioName);
58 | Solved.Visibility = Visibility.Visible;
59 | }
60 | else
61 | {
62 | rootPage.NotifyUser("Sorry, incorrect, try again!", NotifyType.ErrorMessage);
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_04_Beacons.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using System.Diagnostics;
16 | using System.Text.RegularExpressions;
17 |
18 |
19 | namespace BLE_Hackme
20 | {
21 | public sealed partial class Scenario_04_Beacons : Page
22 | {
23 | private MainPage rootPage = MainPage.Current;
24 | private String scenarioName;
25 |
26 |
27 | public Scenario_04_Beacons()
28 | {
29 | this.InitializeComponent();
30 | scenarioName = this.GetType().Name;
31 | }
32 |
33 | protected override async void OnNavigatedTo(NavigationEventArgs e)
34 | {
35 | // set up BLE advertising for this scenario
36 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
37 |
38 | if (ret == false)
39 | {
40 | Debug.WriteLine("Error starting custom advertisement!");
41 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
42 | }
43 |
44 | if (rootPage.isSolved.ContainsKey(scenarioName))
45 | {
46 | if (rootPage.isSolved[scenarioName] == true)
47 | {
48 | Solved.Visibility = Visibility.Visible;
49 | }
50 | }
51 |
52 | }
53 |
54 | private void ValueSubmitButton_Click()
55 | {
56 | //remove everything but digits
57 | Regex onlyDigits = new Regex(@"[^\d]");
58 |
59 | var MajorStr = onlyDigits.Replace(MajorNumber.Text, "");
60 | var MinorStr = onlyDigits.Replace(MinorNumber.Text, "");
61 |
62 | if (!String.IsNullOrEmpty(MajorStr) && !String.IsNullOrEmpty(MinorStr))
63 | {
64 | var Major = Convert.ToUInt16(MajorStr);
65 | var Minor = Convert.ToUInt16(MinorStr);
66 |
67 | if ((Major == rootPage.Ble.iBeaconMajor) && (Minor == rootPage.Ble.iBeaconMinor))
68 | {
69 | rootPage.NotifyCorrect(scenarioName);
70 | Solved.Visibility = Visibility.Visible;
71 | }
72 | }
73 | else
74 | {
75 | rootPage.NotifyUser("Sorry, incorrect, try again!", NotifyType.ErrorMessage);
76 | }
77 | }
78 |
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_05_ManufacturerAdvertisements.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | In the previous task you learned how Manufacturer Specific (0xFF) field can be used to broadcast iBeacon.
24 | It can however transmit any other data - vendors use it for example to identify device type and model, check current status, broadcast temporary id, sensor indication, or just some text.
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | The HackMe should now broadcast other Manufacturer Specific data in place of the iBeacon.
33 | Find out the packet raw payload, and decode its value (skipping Company ID bytes) from ascii hex string into human readable text.
34 | In the advertisement details you can tap on the blue "Manufacturer data" and select a different data display format.
35 |
36 |
37 |
38 | Note: similarly to previous task, the HackMe advertisement is broadcasted again along with your computer's Microsoft broadcast packets
39 | (nRF Connect shows Windows logo icon), which may have higher priority.
40 | If you are having trouble catching the right packet, check the previous task description and hints.
41 |
42 |
43 | By the way, try also scanning various nearby BLE devices: phones, smart TVs, IoT gadgets etc - and check what they advertise.
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | If the custom advertisement data is displayed too shortly in nRF Connect (along with Microsoft advertisements),
64 | you may try to press "stop scanning" in the right moment, and the data will stay static.
65 |
66 |
67 |
68 |
69 |
70 |
71 | Try tapping on the blue "Manufacturer data" in the advertisement details, and then select
72 | "Text" data display format:
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_05_ManufacturerAdvertisements.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using System.Diagnostics;
16 |
17 | namespace BLE_Hackme
18 | {
19 | public sealed partial class Scenario_05_ManufacturerAdvertisements : Page
20 | {
21 | private MainPage rootPage = MainPage.Current;
22 | private String scenarioName;
23 |
24 | public Scenario_05_ManufacturerAdvertisements()
25 | {
26 | this.InitializeComponent();
27 | scenarioName = this.GetType().Name;
28 | }
29 |
30 | protected override async void OnNavigatedTo(NavigationEventArgs e)
31 | {
32 | // set up BLE advertising for this scenario
33 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
34 |
35 | if (ret == false)
36 | {
37 | Debug.WriteLine("Error starting custom advertisement!");
38 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
39 | }
40 |
41 | if (rootPage.isSolved.ContainsKey(scenarioName))
42 | {
43 | if (rootPage.isSolved[scenarioName] == true)
44 | {
45 | Solved.Visibility = Visibility.Visible;
46 | }
47 | }
48 | }
49 |
50 | private void ValueSubmitButton_Click()
51 | {
52 | if (ManufacturerSpecific.Text.Equals($"{Constants.manufacturerSpecificAdvertisementText}{rootPage.Ble.randomForManufacturerSpecific}!", StringComparison.CurrentCultureIgnoreCase))
53 | {
54 | rootPage.NotifyCorrect(scenarioName);
55 | Solved.Visibility = Visibility.Visible;
56 | }
57 | else
58 | {
59 | rootPage.NotifyUser("Sorry, incorrect, try again!", NotifyType.ErrorMessage);
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_06_Connections.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | So far you have passively observed advertisements transmitted by your HackMe device.
24 | It was basically one way communication from Broadcaster to nearby Observers (your smartphone).
25 | The data was publicly available and no pairing was required.
26 |
27 |
28 | Now, you will finally connect and explore another use scenario: where a GATT Client ("Central", your smartphone) connects to GATT Server ("Peripheral", your BLE HackMe device).
29 |
30 |
31 | The GATT (Generic Attribute Profile) is another Bluetooth specification, which organizes data exchange between connected devices.
32 | The main concept introduced here includes so-called Attributes, especially Services and Characteristics:
33 |
34 |
35 | - A Service groups sub-objects (Characteristics) by specific functionality.
36 |
37 |
38 | - A Characteristic is an object holding some information (Value), which can be read or written to.
39 |
40 |
41 | The access rights (read/notify/write) are defined in Characteristic's Properties.
42 |
43 |
44 | Each Service and Characteristic has an
45 | UUID associated. The commonly used UUIDs (for example "battery level", "heart rate", ...) are registered by Bluetooth SIG,
46 | and have a short (16-bit) form. For example: Device Name Characteristic: 0x2A00, Battery Level Characteristic: 0x2A19.
47 |
48 |
49 | For proprietary use, for example switching on/off specific vendor's BLE smart light bulb, manufacturers use their own, full length UUIDs.
50 | They can be randomly generated and don't need to be registered and assigned by Bluetooth organization. Just the associated mobile application (or other connecting device) needs to know it.
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | Your HackMe device should be visible again as your computer hostname (scan again to find it).
59 | Use the "Connect" button to initiate connection. The application will show the list of BLE "services" available on the device.
60 | Some services (including Generic Access and Generic Attribute) are mandatory, and you should see them in every BLE device.
61 |
62 |
63 | Tap on a service name in order to expand characteristics inside of this service. Note the characteristic UUIDs and Properties displayed in the application.
64 |
65 |
66 | Your task is to list all the characteristics' UUIDs of the "Generic Access" service.
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | If you are having trouble connecting to your HackMe device, try switching to previous task (with BLE advertisements) and back.
86 | It will re-start the advertisement (with another Bluetooth address), so you should scan again to find it.
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | The list of Generic Access service characteristics should look like this:
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_06_Connections.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using System.Text.RegularExpressions;
16 | using System.Diagnostics;
17 |
18 | namespace BLE_Hackme
19 | {
20 | public sealed partial class Scenario_06_Connections : Page
21 | {
22 | private MainPage rootPage = MainPage.Current;
23 | private String scenarioName;
24 |
25 | public Scenario_06_Connections()
26 | {
27 | this.InitializeComponent();
28 | scenarioName = this.GetType().Name;
29 | }
30 |
31 | protected override async void OnNavigatedTo(NavigationEventArgs e)
32 | {
33 | // set up BLE advertising for this scenario
34 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
35 |
36 | if (ret == false || rootPage.Ble.lightBulbService == null)
37 | {
38 | Debug.WriteLine("Error, lightbulb service is null!");
39 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
40 | }
41 |
42 | if (rootPage.isSolved.ContainsKey(scenarioName))
43 | {
44 | if (rootPage.isSolved[scenarioName] == true)
45 | {
46 | Solved.Visibility = Visibility.Visible;
47 | }
48 | }
49 |
50 | }
51 |
52 | private void ValueSubmitButton_Click()
53 | {
54 |
55 | String value = ValueToEnter.Text;
56 |
57 | Debug.WriteLine($"Received value: {value}");
58 |
59 | //remove whitespace and "0x"
60 | value = Regex.Replace(value, @"\s+", "");
61 | value = Regex.Replace(value, "0x", "");
62 |
63 | Debug.WriteLine($"Received value after regex: {value}");
64 |
65 | if (value.Equals("2a00,2a01,2a04,2aa6", StringComparison.CurrentCultureIgnoreCase))
66 | {
67 | rootPage.NotifyCorrect(scenarioName);
68 | Solved.Visibility = Visibility.Visible;
69 | }
70 | else
71 | {
72 | rootPage.NotifyUser("Sorry, incorrect, try again!", NotifyType.ErrorMessage);
73 | }
74 | }
75 |
76 | }
77 |
78 | }
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_07_Read.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Each Characteristic has a Value, which can be read or written to, depending on associated permissions - Properties.
25 | The properties can be single (only read or only write), or combined - for example read + write.
26 |
27 |
28 | Access to a characteristic can be additionally restricted by requiring prior pairing with a device (characteristic protection level).
29 | However the majority of devices do not implement this feature, or implement it only for a few selected characteristics.
30 | Therefore accessing characteristics in most of BLE devices does not require Bluetooth pairing, and is available for everyone in range.
31 | Note that there still can be "application layer" security in place, for example some sort of authentication (password),
32 | or data transmitted to/from characteristic can be encrypted by application (not on Bluetooth layer). We will get back to this later.
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | The nRF Connect application shows properties (permissions) as text value,
41 | and additionallly icons for available actions:
42 |
43 |
44 | -
45 |
46 |
47 |
48 | down arrow to read
49 |
50 |
51 |
52 | -
53 |
54 |
55 |
56 | up arrow to write
57 |
58 |
59 | -
60 |
61 |
62 |
63 | multiple down - to subscribe.
64 |
65 |
66 | We will cover writing and subscriptions in upcoming tasks, for now let's start with reading.
67 | Find Battery Level characteristic inside Battery Service, and use the
68 |
69 |
70 |
71 | down arrow to read its value.
72 |
73 |
74 | Try also reading characteristics of other nearby BLE devices. If you are able to get the list of services and characteristics, but can not read the value,
75 | access to the characteristic may require prior pairing.
76 |
77 |
78 | By the way, swiping right (or selecting top right menu -> show log) will show you the low level connection log, which may be useful for debugging.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | After successful read (down arrow by the "Battery Level" characteristic),
98 | current (randomly generated for you) battery level should be displayed in nRF Connect as "Value" below the characteristic UUID/name.
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | The Battery Level characteristic value after reading should look like this:
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_07_Read.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using System.Text.RegularExpressions;
16 | using System.Diagnostics;
17 |
18 | namespace BLE_Hackme
19 | {
20 | public sealed partial class Scenario_07_Read : Page
21 | {
22 | private MainPage rootPage = MainPage.Current;
23 | private String scenarioName;
24 |
25 | public Scenario_07_Read()
26 | {
27 | this.InitializeComponent();
28 | scenarioName = this.GetType().Name;
29 | }
30 |
31 | protected override async void OnNavigatedTo(NavigationEventArgs e)
32 | {
33 | // set up BLE advertising for this scenario
34 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
35 |
36 | if (ret == false || rootPage.Ble.lightBulbService == null)
37 | {
38 | Debug.WriteLine("Error, lightbulb service is null!");
39 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
40 | }
41 |
42 | if (rootPage.isSolved.ContainsKey(scenarioName))
43 | {
44 | if (rootPage.isSolved[scenarioName] == true)
45 | {
46 | Solved.Visibility = Visibility.Visible;
47 | }
48 | }
49 |
50 | }
51 |
52 |
53 | private void ValueSubmitButton_Click()
54 | {
55 |
56 | // clear everything but digits
57 | String value = Regex.Replace(ValueToEnter.Text, @"[^0-9]", "");
58 |
59 | if (value.Equals(rootPage.Ble.batteryService.BatteryLevel.batteryLevelIndication.ToString()))
60 | {
61 | rootPage.NotifyCorrect(scenarioName);
62 | Solved.Visibility = Visibility.Visible;
63 | }
64 | else
65 | {
66 | rootPage.NotifyUser("Sorry, incorrect, try again!", NotifyType.ErrorMessage);
67 | }
68 | }
69 |
70 | }
71 |
72 | }
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_08_Notifications.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Besides reading characteristic value, it is also possible to subscribe to it.
25 | The device will automatically send a notification whenever the value update is available, eliminating the need for manual read.
26 | There are two types of notifications:
27 |
28 |
29 | - Notification ("NOTIFY" property) - without receive confirmation
30 |
31 |
32 | - Indication ("INDICATE" property) - the receiver confirms packet reception to sending device.
33 |
34 |
35 | Characteristic can have both Notify and Indicate or just one of them.
36 | The difference is just in low level Bluetooth packets, the transmitted data is the same, and for application it makes no difference.
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | Connect to your device, find Heart Rate service and its characteristic.
46 | Try reading current Heart Rate Measurement value using single down arrow
47 |
48 |
49 |
50 | . Try it multiple times to see if the value changes in time.
51 |
52 |
53 | Next, subscribe to the Heart Rate Measurement characteristic notification using the subscribe button:
54 |
55 |
56 |
57 | The button will change its status and characteristic value will be updated every second.
58 |
59 |
60 | Your task is to submit current beats per minute value.
61 |
62 |
63 | If needed, you can unsubscribe from notifications by tapping again on the same button.
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | As a result of subscribe action (3 down arrows by "Heart Rate Measurement" characteristic of "Heart Rate" service),
82 | current indication should be visible as "Value" below the characteristic UUID/name.
83 |
84 |
85 |
86 |
87 |
88 |
89 | The Heart Rate Measurement characteristic value should look like this:
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_08_Notifications.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using System.Text.RegularExpressions;
16 | using System.Diagnostics;
17 |
18 | namespace BLE_Hackme
19 | {
20 | public sealed partial class Scenario_08_Notifications : Page
21 | {
22 | private MainPage rootPage = MainPage.Current;
23 | private String scenarioName;
24 |
25 | public Scenario_08_Notifications()
26 | {
27 | this.InitializeComponent();
28 | scenarioName = this.GetType().Name;
29 | }
30 |
31 | protected override async void OnNavigatedTo(NavigationEventArgs e)
32 | {
33 | // set up BLE advertising for this scenario
34 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
35 |
36 | if (ret == false || rootPage.Ble.lightBulbService == null)
37 | {
38 | Debug.WriteLine("Error, lightbulb service is null!");
39 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
40 | }
41 |
42 | if (rootPage.isSolved.ContainsKey(scenarioName))
43 | {
44 | if (rootPage.isSolved[scenarioName] == true)
45 | {
46 | Solved.Visibility = Visibility.Visible;
47 | }
48 | }
49 |
50 | }
51 |
52 | private void ValueSubmitButton_Click()
53 | {
54 | // clear everything but digits, convert to int
55 | int submittedValue = Int16.Parse(Regex.Replace(ValueToEnter.Text, @"[^0-9]", ""));
56 |
57 | if ( (submittedValue < rootPage.Ble.heartRateService.HeartRateMeasurement.currentHeartRate + 5) &&
58 | (submittedValue > rootPage.Ble.heartRateService.HeartRateMeasurement.currentHeartRate - 5) )
59 | {
60 | rootPage.NotifyCorrect(scenarioName);
61 | Solved.Visibility = Visibility.Visible;
62 | }
63 | else
64 | {
65 | rootPage.NotifyUser("Sorry, incorrect, try again!", NotifyType.ErrorMessage);
66 | }
67 | }
68 |
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_09_Descriptors.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Characteristic can have optional Descriptor associated. Most commonly used descriptors:
25 |
26 |
27 | - User Text Description (0x2901): human readable text, for example "command", "battery level"
28 |
29 |
30 | -
31 | Client Characteristic Configuration (0x2902) shows current status of subscription: unsubscribed, subscribed for notifications, subscribed to indications.
32 |
33 |
34 | Services, Characteristics and Descriptors are also called Attributes.
35 | Hence the Bluetooth specification defining them is called GATT (Generic Attribute Profile).
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | Check descriptors associated with Heart Rate Measurement characteristic.
44 | Note how Client Characteristic Configuration (0x2902) value changes after signing up to/signing off from notifications.
45 | The nRF Connect displays here the human readable text description,
46 | but if you are interested in low level details, uncheck "Parse known characteristics" option in the top right menu to see
47 | the hex value: 0x0000 = unsubscribed, 0x0100 = subscribed for notifications, 0x0200 = subscribed to indications.
48 |
49 |
50 | Second available descriptor for Heart Rate Measurement characteristic is the User Text Description (0x2901).
51 | Your task is to submit its value. You can read it using the down arrow associated.
52 |
53 |
54 | By the way, this text descriptor also has an up arrow available - indicating possible write, not only read.
55 | Just ignore it, writing is not actually available here.
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | After tapping the down arrow by 0x2901 Descriptor below "Heart Rate Measurement" characteristic, you should see the text description as its "Value".
74 | It is a human readable text with a few randomly generated numbers at the end.
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | The 0x2901 descriptor text value should look like this:
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_09_Descriptors.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using System.Diagnostics;
16 |
17 | namespace BLE_Hackme
18 | {
19 | public sealed partial class Scenario_09_Descriptors : Page
20 | {
21 | private MainPage rootPage = MainPage.Current;
22 | private String scenarioName;
23 |
24 | public Scenario_09_Descriptors()
25 | {
26 | this.InitializeComponent();
27 | scenarioName = this.GetType().Name;
28 | }
29 |
30 | protected override async void OnNavigatedTo(NavigationEventArgs e)
31 | {
32 | // set up BLE advertising for this scenario
33 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
34 |
35 | if (ret == false || rootPage.Ble.lightBulbService == null)
36 | {
37 | Debug.WriteLine("Error, lightbulb service is null!");
38 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
39 | }
40 |
41 | if (rootPage.isSolved.ContainsKey(scenarioName))
42 | {
43 | if (rootPage.isSolved[scenarioName] == true)
44 | {
45 | Solved.Visibility = Visibility.Visible;
46 | }
47 | }
48 |
49 | }
50 |
51 | private void ValueSubmitButton_Click()
52 | {
53 |
54 | if (ValueToEnter.Text.Equals($"{Constants.heartRateDescriptorText}{rootPage.Ble.heartRateService.randomForDescriptor}", StringComparison.CurrentCultureIgnoreCase))
55 | {
56 | rootPage.NotifyCorrect(scenarioName);
57 | Solved.Visibility = Visibility.Visible;
58 | }
59 | else
60 | {
61 | rootPage.NotifyUser("Sorry, incorrect, try again!", NotifyType.ErrorMessage);
62 | }
63 | }
64 |
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_10_Write.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | So far you have learned how to receive data from device by reading and subcribing to characteristic value.
24 | Characteristics may also have a "write" property, which allows for submitting a value to device.
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Using your new skills in regards to services, characteristics and descriptors,
34 | connect to your HackMe device, find proprietary service responsible for light bulb control, and a characteristic inside it that allows to switch the light on and off.
35 | Read the current state of the switch, and try to turn it on.
36 |
37 |
38 | In nRF Connect use the up arrow
39 |
40 |
41 |
42 | by the characteristic to write a value to it.
43 | Once succeeded, you can turn the light off again if you like.
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | As opposed to typical, Bluetooth registered services, the proprietary service and its characteristics will have full length UUIDs.
56 |
57 |
58 |
59 |
60 |
61 | Check the 0x2901 Text Descriptor value to find which characteristic is responsible for light bulb switching.
62 |
63 |
64 |
65 |
66 |
67 | Get current state of the light bulb (off) by reading first characteristic of first proprietary (long UUID) service.
68 | How do you think, what would be the value for "on"?
69 |
70 |
71 |
72 |
73 |
74 |
75 | After selecting up arrow by the light bulb switch characteristic,
76 | the application should present you with the write value form:
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | You can send proper value as byte:
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_10_Write.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using Windows.Devices.Bluetooth;
16 | using System.Diagnostics;
17 | using Windows.Media.SpeechSynthesis;
18 | using Windows.Security.Cryptography;
19 | using BLE_Hackme.UserControls;
20 | using Windows.UI.Core;
21 |
22 | namespace BLE_Hackme
23 | {
24 | public sealed partial class Scenario_10_Write : Page
25 | {
26 | private MainPage rootPage = MainPage.Current;
27 | SolidColorBrush lightBulbBrush = new SolidColorBrush();
28 | private String scenarioName;
29 | private bool isSolved = false;
30 |
31 |
32 | public Scenario_10_Write()
33 | {
34 | this.InitializeComponent();
35 | scenarioName = this.GetType().Name;
36 | }
37 |
38 | protected override async void OnNavigatedTo(NavigationEventArgs e)
39 | {
40 | // set up BLE advertising for this scenario
41 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
42 | if (ret == true && rootPage.Ble.lightBulbService != null)
43 | {
44 | rootPage.Ble.lightBulbService.LightBulbSwitch.PropertyChanged += Service_PropertyChanged;
45 | }
46 | else
47 | {
48 | Debug.WriteLine("Error, lightbulb service is null!");
49 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
50 | }
51 | if (rootPage.isSolved.ContainsKey(scenarioName))
52 | {
53 | if (rootPage.isSolved[scenarioName] == true)
54 | {
55 | Solved.Visibility = Visibility.Visible;
56 | }
57 | }
58 |
59 | // turn on if previously set state
60 | var currentValue = BLEServices.Helpers.ToHexString(rootPage.Ble.lightBulbService.LightBulbSwitch.Value);
61 | if (currentValue == "01")
62 | {
63 | LightBulb.On();
64 | }
65 |
66 | }
67 |
68 | private void Service_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
69 | {
70 |
71 | if (e.PropertyName.Equals("InvalidRequest"))
72 | {
73 | rootPage.NotifyUser("Invalid request!", NotifyType.ErrorMessage);
74 | }
75 |
76 | //new characteristic value received
77 | if (e.PropertyName.Equals("Value"))
78 | {
79 | // switch (sender) ...
80 | Debug.WriteLine($"Lightbulb service received value from : {sender}");
81 |
82 | String receivedWrite = BLEServices.Helpers.ToHexString(rootPage.Ble.lightBulbService.LightBulbSwitch.Value);
83 | rootPage.NotifyUser("WRITE received: " + receivedWrite, NotifyType.StatusMessage);
84 |
85 | //check if value is 01, otherwise error?
86 | if (receivedWrite.Equals("01"))
87 | {
88 | LightBulb.On();
89 | if (isSolved == false)
90 | {
91 | isSolved = true;
92 | rootPage.NotifyCorrect(scenarioName);
93 | Solved.Visibility = Visibility.Visible;
94 | }
95 | }
96 | else if (receivedWrite.Equals("00"))
97 | {
98 | LightBulb.Off();
99 | }
100 | }
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_11_WriteCommand.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using Windows.Devices.Bluetooth;
16 | using System.Diagnostics;
17 | using Windows.Media.SpeechSynthesis;
18 | using Windows.Security.Cryptography;
19 | using BLE_Hackme.UserControls;
20 | using Windows.UI.Core;
21 | using System.Text.RegularExpressions;
22 |
23 |
24 | namespace BLE_Hackme
25 | {
26 | public sealed partial class Scenario_11_WriteCommand : Page
27 | {
28 | private MainPage rootPage = MainPage.Current;
29 | private String scenarioName;
30 | private bool isSolved;
31 |
32 | private SpeechSynthesizer synth;
33 | private SpeechSynthesisStream speechStream;
34 |
35 | public Scenario_11_WriteCommand()
36 | {
37 | this.InitializeComponent();
38 | scenarioName = this.GetType().Name;
39 |
40 | synth = new SpeechSynthesizer();
41 | }
42 |
43 | protected override async void OnNavigatedTo(NavigationEventArgs e)
44 | {
45 | // set up BLE advertising for this scenario
46 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
47 | if (ret == true && rootPage.Ble.lightBulbService != null)
48 | {
49 | rootPage.Ble.lightBulbService.LightBulbTTS.PropertyChanged += ServiceTTS_PropertyChanged;
50 | }
51 | else
52 | {
53 | Debug.WriteLine("Error, lightbulb service is null!");
54 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
55 | }
56 | if (rootPage.isSolved.ContainsKey(scenarioName))
57 | {
58 | if (rootPage.isSolved[scenarioName] == true)
59 | {
60 | Solved.Visibility = Visibility.Visible;
61 | }
62 | }
63 | }
64 |
65 | private async void GenerateTTS(String whatToSay)
66 | {
67 | speechStream = await synth.SynthesizeTextToStreamAsync(whatToSay);
68 | TextToSpeech.AutoPlay = true;
69 | TextToSpeech.SetSource(speechStream, speechStream.ContentType);
70 | TextToSpeech.Play();
71 | }
72 |
73 | private void ServiceTTS_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
74 | {
75 | if (e.PropertyName.Equals("InvalidRequest"))
76 | {
77 | rootPage.NotifyUser("Invalid request! Did you send write command?", NotifyType.ErrorMessage);
78 | }
79 |
80 | //new characteristic value received
81 | if (e.PropertyName.Equals("Value"))
82 | {
83 | Debug.WriteLine($"Lightbulb service received from : {sender}");
84 |
85 | byte[] receivedWrite;
86 | CryptographicBuffer.CopyToByteArray(rootPage.Ble.lightBulbService.LightBulbTTS.Value, out receivedWrite);
87 | String receivedText = System.Text.Encoding.UTF8.GetString(receivedWrite);
88 |
89 | Debug.WriteLine($"TTS received value: {receivedText}");
90 | //remove excessive characters
91 | receivedText = Regex.Replace(receivedText, @"[^a-zA-Z0-9 -]", "");
92 | Debug.WriteLine($"TTS received value after removing special characters: {receivedText}");
93 |
94 | if (receivedText.Length == 0)
95 | {
96 | rootPage.NotifyUser("Received TTS request, but no readable text value", NotifyType.ErrorMessage);
97 | }
98 | else
99 | {
100 | var task = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => GenerateTTS(receivedText));
101 | if (receivedText.StartsWith("Hello", StringComparison.OrdinalIgnoreCase))
102 | {
103 | if (isSolved == false)
104 | {
105 | isSolved = true;
106 | rootPage.NotifyCorrect(scenarioName);
107 | Solved.Visibility = Visibility.Visible;
108 | LightBulb.Checked(true);
109 | }
110 | }
111 | else
112 | {
113 | rootPage.NotifyUser($"Received TTS text: {receivedText}. How about saying hello?", NotifyType.StatusMessage);
114 | }
115 | }
116 | }
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_12_Macros.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using Windows.Devices.Bluetooth;
16 | using System.Diagnostics;
17 |
18 | namespace BLE_Hackme
19 | {
20 | public sealed partial class Scenario_12_Macros : Page
21 | {
22 | private MainPage rootPage = MainPage.Current;
23 | private String scenarioName;
24 | private bool isSolved = false;
25 |
26 |
27 | public Scenario_12_Macros()
28 | {
29 | this.InitializeComponent();
30 | scenarioName = this.GetType().Name;
31 |
32 | }
33 |
34 | protected override async void OnNavigatedTo(NavigationEventArgs e)
35 | {
36 | // set up BLE advertising for this scenario
37 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
38 |
39 | if (ret == true && rootPage.Ble.lightBulbService != null)
40 | {
41 | rootPage.Ble.lightBulbService.LightBulbSwitch.PropertyChanged += Service_PropertyChanged;
42 | }
43 | else
44 | {
45 | Debug.WriteLine("Error, lightbulb service is null!");
46 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
47 | }
48 |
49 |
50 | if (rootPage.isSolved.ContainsKey(scenarioName))
51 | {
52 | if (rootPage.isSolved[scenarioName] == true)
53 | {
54 | Solved.Visibility = Visibility.Visible;
55 | }
56 | }
57 | }
58 |
59 |
60 | private void Service_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
61 | {
62 |
63 | if (e.PropertyName.Equals("InvalidRequest"))
64 | {
65 | rootPage.NotifyUser("Invalid request!", NotifyType.ErrorMessage);
66 | }
67 |
68 | else if (e.PropertyName.Equals("BlinkPassed"))
69 | {
70 | rootPage.NotifyCorrect(scenarioName);
71 | Solved.Visibility = Visibility.Visible;
72 | LightBulb.Checked(true);
73 | isSolved = true;
74 | }
75 |
76 | //new characteristic value received
77 | else if (e.PropertyName.Equals("Value"))
78 | {
79 | String receivedWrite = BLEServices.Helpers.ToHexString(rootPage.Ble.lightBulbService.LightBulbSwitch.Value);
80 |
81 | // notify of every write until solved, otherwise it will overwrite the "congratulations" notification
82 | if (!isSolved)
83 | {
84 | rootPage.NotifyUser("Write received: " + receivedWrite, NotifyType.StatusMessage);
85 | }
86 |
87 | if (receivedWrite.Equals("01"))
88 | {
89 | LightBulb.On();
90 | }
91 | else if (receivedWrite.Equals("00"))
92 | {
93 | LightBulb.Off();
94 | }
95 | }
96 | }
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_13_RGB.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using Windows.Devices.Bluetooth;
16 | using System.Diagnostics;
17 | using Windows.Security.Cryptography;
18 |
19 | namespace BLE_Hackme
20 | {
21 | public sealed partial class Scenario_13_RGB : Page
22 | {
23 | private MainPage rootPage = MainPage.Current;
24 | private String scenarioName;
25 | SolidColorBrush lightBulbBrush = new SolidColorBrush();
26 |
27 | public Scenario_13_RGB()
28 | {
29 | this.InitializeComponent();
30 | scenarioName = this.GetType().Name;
31 | }
32 |
33 | protected override async void OnNavigatedTo(NavigationEventArgs e)
34 | {
35 | // set up BLE advertising for this scenario
36 | var ret = await rootPage.Ble.AdvertisingForScenario(scenarioName);
37 |
38 | if (ret == true && rootPage.Ble.lightBulbService != null)
39 | {
40 | rootPage.Ble.lightBulbService.LightBulbColor.PropertyChanged += Service_PropertyChanged;
41 | }
42 | else
43 | {
44 | Debug.WriteLine("Error, lightbulb service is null!");
45 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
46 | }
47 |
48 | if (rootPage.isSolved.ContainsKey(scenarioName))
49 | {
50 | if (rootPage.isSolved[scenarioName] == true)
51 | {
52 | Solved.Visibility = Visibility.Visible;
53 | }
54 | }
55 | }
56 |
57 | private void Service_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
58 | {
59 |
60 | if (e.PropertyName.Equals("InvalidRequest"))
61 | {
62 | rootPage.NotifyUser("Invalid request!", NotifyType.ErrorMessage);
63 | }
64 |
65 | //new characteristic value received
66 | if (e.PropertyName.Equals("Value"))
67 | {
68 | byte[] newColor = rootPage.Ble.lightBulbService.LightBulbColor.argb;
69 | rootPage.NotifyUser($"New color received: {newColor[0]} {newColor[1]} {newColor[2]} {newColor[3]}", NotifyType.StatusMessage);
70 |
71 | //initial check already in the characteristic, assuming [A R G B] here
72 | lightBulbBrush.Color = Windows.UI.Color.FromArgb(newColor[0], newColor[1], newColor[2], newColor[3]);
73 | LightBulb.ARGB(lightBulbBrush);
74 |
75 | //check if half dim red (FF0000) received
76 | if ((newColor[0] > 110) && (newColor[0] < 150) && (newColor[1] == 255) && (newColor[1] == 255) && (newColor[2]==0) && (newColor[3] == 0))
77 | {
78 | rootPage.NotifyCorrect(scenarioName);
79 | Solved.Visibility = Visibility.Visible;
80 | }
81 | }
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_15_QuickLockReplay.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using Windows.Devices.Bluetooth;
16 | using System.Diagnostics;
17 | using Windows.Security.Cryptography;
18 | using Windows.Media.SpeechSynthesis;
19 | using Windows.System;
20 | using System.Threading;
21 | using System.Threading.Tasks;
22 |
23 |
24 |
25 | namespace BLE_Hackme
26 | {
27 | public sealed partial class Scenario_15_QuickLockReplay : Page
28 | {
29 | private MainPage rootPage = MainPage.Current;
30 | private String scenarioName;
31 | SpeechSynthesizer synth = new SpeechSynthesizer();
32 | SpeechSynthesisStream speechStream;
33 |
34 | public Scenario_15_QuickLockReplay()
35 | {
36 | this.InitializeComponent();
37 | scenarioName = this.GetType().Name;
38 | }
39 |
40 |
41 | protected override async void OnNavigatedTo(NavigationEventArgs e)
42 | {
43 | // set up BLE advertising for this scenario
44 | var ret = await rootPage.Ble.AdvertisingForScenario(this.GetType().Name);
45 |
46 | if (ret == true && rootPage.Ble.quickLockMainService != null)
47 | {
48 | rootPage.Ble.quickLockMainService.QuickLockAuth.PropertyChanged += Service_PropertyChanged;
49 | rootPage.Ble.quickLockMainService.QuickLockCommand.PropertyChanged += Service_PropertyChanged;
50 |
51 | //initialize speech stream
52 | speechStream = await synth.SynthesizeTextToStreamAsync($"Unlocking! Locking again in 3,,,,, 2,,,,, 1,,,,, ");
53 |
54 | VoiceUnlocking.SetSource(speechStream, speechStream.ContentType);
55 | VoiceUnlocking.AutoPlay = false;
56 | // lock it again after playing
57 | VoiceUnlocking.MediaEnded += LockAgain;
58 |
59 | }
60 | else
61 | {
62 | Debug.WriteLine("Error, quicklock main service is null!");
63 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
64 | }
65 |
66 | if (rootPage.isSolved.ContainsKey(scenarioName))
67 | {
68 | if (rootPage.isSolved[scenarioName] == true)
69 | {
70 | Solved.Visibility = Visibility.Visible;
71 | }
72 | }
73 |
74 | }
75 |
76 | private void Service_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
77 | {
78 | if (e.PropertyName.Equals("InvalidRequest"))
79 | {
80 | rootPage.NotifyUser("Invalid request!", NotifyType.ErrorMessage);
81 | }
82 |
83 | else if (e.PropertyName.Equals("InvalidPin"))
84 | {
85 | rootPage.NotifyUser("Invalid password, access denied!", NotifyType.ErrorMessage);
86 | }
87 |
88 | else if (e.PropertyName.Equals("Unauthenticated"))
89 | {
90 | rootPage.NotifyUser("Unauthenticated, access denied!", NotifyType.ErrorMessage);
91 | }
92 |
93 |
94 | // new command value received only after successful authentication
95 | if (e.PropertyName.Equals("LockState"))
96 | {
97 |
98 | Debug.WriteLine("Received LockState update");
99 |
100 | if (rootPage.Ble.quickLockMainService.isUnlocked)
101 | {
102 | rootPage.NotifyCorrect(scenarioName);
103 | Solved.Visibility = Visibility.Visible;
104 | //tbd next time (if isSolved)
105 | // rootPage.NotifyUser($"Correct password, unlocking!", NotifyType.StatusMessage);
106 | SmartLock.Unlock();
107 |
108 | //VoiceUnlocking.AutoPlay = true;
109 | VoiceUnlocking.Play();
110 | }
111 | //received "lock" command, but it should be locked anyway ;)
112 | else
113 | {
114 | rootPage.NotifyUser("Locking...", NotifyType.StatusMessage);
115 | SmartLock.Lock();
116 | }
117 |
118 | }
119 | }
120 |
121 | private void LockAgain(object Sender, RoutedEventArgs e)
122 | {
123 | Debug.WriteLine("Locking again");
124 | SmartLock.Lock();
125 |
126 | rootPage.Ble.quickLockMainService.UpdateAuthenticationState(false);
127 | rootPage.Ble.quickLockMainService.UpdateUnlockState(false);
128 |
129 | }
130 |
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_16_QuickLockLogs.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using Windows.Devices.Bluetooth;
16 | using System.Diagnostics;
17 | using Windows.Security.Cryptography;
18 | using Windows.Media.SpeechSynthesis;
19 | using Windows.System;
20 | using System.Threading;
21 |
22 |
23 | namespace BLE_Hackme
24 | {
25 | public sealed partial class Scenario_16_QuickLockLogs : Page
26 | {
27 | private MainPage rootPage = MainPage.Current;
28 | private String scenarioName;
29 |
30 | public Scenario_16_QuickLockLogs()
31 | {
32 | this.InitializeComponent();
33 | scenarioName = this.GetType().Name;
34 | }
35 |
36 | protected override async void OnNavigatedTo(NavigationEventArgs e)
37 | {
38 | // set up BLE advertising for this scenario
39 | var ret = await rootPage.Ble.AdvertisingForScenario(this.GetType().Name);
40 |
41 | if (ret == false || rootPage.Ble.quickLockMainService == null)
42 | {
43 | Debug.WriteLine("Error, quicklock main service is null!");
44 | rootPage.NotifyUser("Problem starting device simulation", NotifyType.ErrorMessage, NotifyButton.RestartDevice);
45 | }
46 |
47 | if (rootPage.isSolved.ContainsKey(scenarioName))
48 | {
49 | if (rootPage.isSolved[scenarioName] == true)
50 | {
51 | Solved.Visibility = Visibility.Visible;
52 | }
53 | }
54 | }
55 |
56 |
57 | private void ValueSubmitButton_Click()
58 | {
59 | var correctDate = new DateTime(2020, 11, 7);
60 |
61 | // the date provided by CalendarDatePicker (UnlockDate) is with current time, in order to compare it we need to clean it first
62 | if (UnlockDate.Date.HasValue)
63 | {
64 | var dateVal = UnlockDate.Date.Value;
65 | var enteredDate = new DateTime(dateVal.Year, dateVal.Month, dateVal.Day);
66 |
67 | Debug.WriteLine($"Entered username: {ValueToEnter.Text}; entered date: {enteredDate}; expected date: {correctDate}");
68 | if (ValueToEnter.Text.Equals("hackmeuser", StringComparison.CurrentCultureIgnoreCase) && enteredDate.Equals(correctDate))
69 | {
70 | rootPage.NotifyCorrect(scenarioName);
71 |
72 | Solved.Visibility = Visibility.Visible;
73 | }
74 | else
75 | {
76 | rootPage.NotifyUser("Sorry, incorrect, try again!", NotifyType.ErrorMessage);
77 | }
78 | }
79 | else
80 | {
81 | rootPage.NotifyUser("Please enter the date!", NotifyType.ErrorMessage);
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_Summary.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Congratulations!!!
39 |
40 |
41 | If you are interested in more, please check
42 | www.smartlockpicking.com
43 | for updates.
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/cs/Scenarios/Scenario_Summary.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 | using Windows.Devices.Bluetooth;
16 | using System.Diagnostics;
17 | using Windows.Security.Cryptography;
18 | using Windows.Media.SpeechSynthesis;
19 | using Windows.System;
20 | using System.Threading;
21 |
22 |
23 | namespace BLE_Hackme
24 | {
25 | public sealed partial class Scenario_Summary : Page
26 | {
27 | private MainPage rootPage = MainPage.Current;
28 | private int solvedCount;
29 |
30 | public Scenario_Summary()
31 | {
32 | this.InitializeComponent();
33 | }
34 |
35 | protected override void OnNavigatedTo(NavigationEventArgs e)
36 | {
37 | solvedCount = 0;
38 |
39 | //generate list of scenarios
40 | foreach (Scenario sc in rootPage.Scenarios)
41 | {
42 | ListScenario(sc);
43 | }
44 |
45 | //update solved count header
46 | CurrentStatusText.Text = $"{solvedCount} task";
47 | if ((solvedCount ==0) || (solvedCount > 1))
48 | {
49 | CurrentStatusText.Text += "s";
50 | }
51 | CurrentStatusText.Text += $" of {rootPage.numberOfTasks} solved";
52 |
53 | if(solvedCount == rootPage.numberOfTasks)
54 | {
55 | allSolved();
56 | }
57 | }
58 |
59 | private void ListScenario(Scenario sc)
60 | {
61 | string className = sc.ClassType.Name;
62 |
63 | // do not add Start and Summary pages
64 | if (className.Equals("Scenario_01_Compatibility") || className.Equals("Scenario_Summary"))
65 | {
66 | return;
67 | }
68 |
69 | StackPanel newSp = new StackPanel();
70 | newSp.Orientation = Orientation.Horizontal;
71 | newSp.Margin = new Thickness(10, 5, 0, 0);
72 |
73 | FontIcon newIcon = new FontIcon();
74 | newIcon.Foreground = new SolidColorBrush(Windows.UI.Colors.DarkGray);
75 | newIcon.FontFamily = new FontFamily("Segoe MDL2 Assets");
76 | newIcon.FontSize = 15;
77 | newIcon.Glyph = "\uF16B";
78 | newIcon.Margin = new Thickness(0, 0, 5, 0);
79 |
80 | HyperlinkButton newHl = new HyperlinkButton();
81 | newHl.Foreground = newIcon.Foreground;
82 | newHl.Margin = new Thickness(0, 0, 0, 0);
83 | newHl.Click += scenarioLinkClick;
84 | newHl.Content = sc.Title;
85 | newHl.Padding = new Thickness(0, 0, 0, 0);
86 |
87 | if (rootPage.isSolved.ContainsKey(className))
88 | {
89 | if (rootPage.isSolved[className] == true)
90 | {
91 | newIcon.Foreground = new SolidColorBrush(Windows.UI.Colors.MediumSpringGreen);
92 | newHl.Foreground = newIcon.Foreground;
93 | newIcon.Glyph = "\uF16C";
94 | solvedCount++;
95 | }
96 | }
97 | newSp.Children.Add(newIcon);
98 | newSp.Children.Add(newHl);
99 | ListOfScenarios.Children.Add(newSp);
100 | }
101 |
102 | void scenarioLinkClick(object sender, RoutedEventArgs e)
103 | {
104 | var name = (sender as HyperlinkButton).Content.ToString();
105 | rootPage.NavigateScenarioByTitle(name);
106 | }
107 |
108 | void allSolved()
109 | {
110 | // show trophy
111 | Trophy.Visibility = Visibility.Visible;
112 | CongratulationText.Visibility = Visibility.Visible;
113 | // play applause
114 | Applause.AutoPlay = true;
115 | Applause.Play();
116 |
117 | //manually enforce 100% progress, as partial % may not add to 100
118 | rootPage.SetProgress(100);
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/cs/ScenariosConfiguration.cs:
--------------------------------------------------------------------------------
1 |
2 | using BLE_Hackme.UserControls;
3 | using System;
4 | using System.Collections.Generic;
5 | using Windows.ApplicationModel.Background;
6 | using Windows.Storage;
7 | using Windows.UI.Xaml.Controls;
8 |
9 | namespace BLE_Hackme
10 | {
11 | public partial class MainPage : Page
12 | {
13 | List scenarios = new List
14 | {
15 | new Scenario() { Title="Start", ClassType=typeof(Scenario_01_Compatibility) },
16 | new Scenario() { Title="First steps", ClassType=typeof(Scenario_02_Intro) },
17 | new Scenario() { Title="BLE Advertisements", ClassType=typeof(Scenario_03_Advertisements) },
18 | new Scenario() { Title="Beacons", ClassType=typeof(Scenario_04_Beacons) },
19 | new Scenario() { Title="Manufacturer Specific Advertisements", ClassType=typeof(Scenario_05_ManufacturerAdvertisements) },
20 | new Scenario() { Title="Connections, services, characteristics", ClassType=typeof(Scenario_06_Connections) },
21 | new Scenario() { Title="Characteristic read", ClassType=typeof(Scenario_07_Read) },
22 | new Scenario() { Title="Notifications", ClassType=typeof(Scenario_08_Notifications) },
23 | new Scenario() { Title="Descriptors", ClassType=typeof(Scenario_09_Descriptors) },
24 | new Scenario() { Title="Characteristic write", ClassType=typeof(Scenario_10_Write) },
25 | new Scenario() { Title="Various writes", ClassType=typeof(Scenario_11_WriteCommand) },
26 | new Scenario() { Title="Write automation", ClassType=typeof(Scenario_12_Macros) },
27 | new Scenario() { Title="Protocol reverse-engineering", ClassType=typeof(Scenario_13_RGB) },
28 | new Scenario() { Title="Password brute force", ClassType=typeof(Scenario_14_PasswordBrute) },
29 | new Scenario() { Title="Smart lock replay", ClassType=typeof(Scenario_15_QuickLockReplay) },
30 | new Scenario() { Title="Smart lock information leak", ClassType=typeof(Scenario_16_QuickLockLogs) },
31 | new Scenario() { Title="Summary", ClassType=typeof(Scenario_Summary) },
32 | };
33 | }
34 |
35 | public class Scenario
36 | {
37 | public string Title { get; set; }
38 | public Type ClassType { get; set; }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/cs/UserControls/LightBulbUserControl.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/cs/UserControls/LightBulbUserControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 | namespace BLE_Hackme.UserControls
17 | {
18 | public sealed partial class LightBulbUserControl : UserControl
19 | {
20 | private SolidColorBrush colorBrush;
21 | public LightBulbUserControl()
22 | {
23 | this.InitializeComponent();
24 | colorBrush = new SolidColorBrush();
25 | }
26 |
27 | public void ARGB(SolidColorBrush brush)
28 | {
29 | LightBulbIn.Foreground = brush;
30 | // LightBulbOut.Foreground = brush;
31 | }
32 |
33 | public void On()
34 | {
35 | //colorBrush.Color = Windows.UI.Colors.Yellow;
36 | colorBrush.Color = Windows.UI.Color.FromArgb(0xFF, 0xFF, 0xFF, 0xA0);
37 | LightBulbIn.Foreground = colorBrush;
38 | }
39 |
40 | public void Off()
41 | {
42 | colorBrush.Color = Windows.UI.Colors.Black;
43 | LightBulbIn.Foreground = colorBrush;
44 | }
45 |
46 | public void Checked(bool on)
47 | {
48 | if (on)
49 | {
50 | LightBulbChecked.Visibility = Visibility.Visible;
51 | LightBulbOut.Visibility = Visibility.Collapsed;
52 | }
53 | else
54 | {
55 | LightBulbChecked.Visibility = Visibility.Collapsed;
56 | LightBulbOut.Visibility = Visibility.Visible;
57 | }
58 | }
59 |
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderHints.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderHints.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 | namespace BLE_Hackme.UserControls
17 | {
18 | public sealed partial class ScenarioSubHeaderHints : UserControl
19 | {
20 | private MainPage rootPage = MainPage.Current;
21 | private int currentHint = 0;
22 |
23 | public ScenarioSubHeaderHints()
24 | {
25 | this.InitializeComponent();
26 | }
27 |
28 | private void HintButton_Click(object sender, RoutedEventArgs e)
29 | {
30 | currentHint++;
31 | String hintName = $"Hint{currentHint}";
32 |
33 | // scrollviewer in Page
34 | var sv = (ScrollViewer)((FrameworkElement)this.Parent).Parent;
35 | // var page = (Page) sv.Parent;
36 |
37 | StackPanel hintPanel = sv.FindName(hintName) as StackPanel;
38 | if (hintPanel != null)
39 | {
40 | hintPanel.Visibility = Visibility.Visible;
41 | }
42 | else
43 | {
44 | rootPage.NotifyUser("Sorry, no more hints...", NotifyType.StatusMessage);
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderIntro.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderIntro.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 | // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
17 |
18 | namespace BLE_Hackme.UserControls
19 | {
20 | public sealed partial class ScenarioSubHeaderIntro : UserControl
21 | {
22 | public ScenarioSubHeaderIntro()
23 | {
24 | this.InitializeComponent();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderSimulatedDevice.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderSimulatedDevice.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 |
17 | namespace BLE_Hackme.UserControls
18 | {
19 | public sealed partial class ScenarioSubHeaderSimulatedDevice : UserControl
20 | {
21 | public ScenarioSubHeaderSimulatedDevice()
22 | {
23 | this.InitializeComponent();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderSubmit.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderSubmit.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 |
17 | namespace BLE_Hackme.UserControls
18 | {
19 | public sealed partial class ScenarioSubHeaderSubmit : UserControl
20 | {
21 | public ScenarioSubHeaderSubmit()
22 | {
23 | this.InitializeComponent();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderTask.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/cs/UserControls/ScenarioSubHeaderTask.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 | namespace BLE_Hackme.UserControls
17 | {
18 | public sealed partial class ScenarioSubHeaderTask : UserControl
19 | {
20 | public ScenarioSubHeaderTask()
21 | {
22 | this.InitializeComponent();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/cs/UserControls/SmartLockUserControl.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/cs/UserControls/SmartLockUserControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 |
17 | namespace BLE_Hackme.UserControls
18 | {
19 | public sealed partial class SmartLockUserControl : UserControl
20 | {
21 | public SmartLockUserControl()
22 | {
23 | this.InitializeComponent();
24 | }
25 |
26 | public void Unlock()
27 | {
28 | SmartLockUnlocked.Visibility = Visibility.Visible;
29 | SmartLockLocked.Visibility = Visibility.Collapsed;
30 | }
31 |
32 | public void Lock()
33 | {
34 | SmartLockLocked.Visibility = Visibility.Visible;
35 | SmartLockUnlocked.Visibility = Visibility.Collapsed;
36 | }
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlockpicking/BLE_HackMe/8e47cbcd2addd5b135202585150f9e44f5540a67/logo.png
--------------------------------------------------------------------------------