├── LICENSE.txt
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── laas
│ │ │ └── rcayre
│ │ │ └── radiosploit
│ │ │ ├── HciInterface.java
│ │ │ ├── MainActivity.java
│ │ │ ├── PacketItemData.java
│ │ │ ├── PacketListAdapter.java
│ │ │ ├── PatchFragment.java
│ │ │ ├── dissectors
│ │ │ ├── Dissector.java
│ │ │ ├── EsbDissector.java
│ │ │ ├── MosartDissector.java
│ │ │ └── ZigbeeDissector.java
│ │ │ └── ui
│ │ │ ├── esb
│ │ │ ├── EsbBus.java
│ │ │ ├── EsbDevice.java
│ │ │ ├── EsbDeviceBus.java
│ │ │ ├── EsbDevicePacketListAdapter.java
│ │ │ ├── EsbDevicesList.java
│ │ │ ├── EsbEditDialogFragment.java
│ │ │ ├── EsbFragment.java
│ │ │ ├── EsbRxFragment.java
│ │ │ ├── EsbRxPacketListAdapter.java
│ │ │ ├── EsbRxThread.java
│ │ │ ├── EsbScanFragment.java
│ │ │ ├── EsbScanThread.java
│ │ │ ├── EsbTabAdapter.java
│ │ │ ├── EsbTxFragment.java
│ │ │ ├── EsbTxPacketListAdapter.java
│ │ │ ├── EsbTxThread.java
│ │ │ └── EsbVisualizeDialogFragment.java
│ │ │ ├── mosart
│ │ │ ├── MosartBus.java
│ │ │ ├── MosartDevice.java
│ │ │ ├── MosartDeviceBus.java
│ │ │ ├── MosartDevicePacketListAdapter.java
│ │ │ ├── MosartDevicesList.java
│ │ │ ├── MosartEditDialogFragment.java
│ │ │ ├── MosartFragment.java
│ │ │ ├── MosartKeyloggerFragment.java
│ │ │ ├── MosartKeyloggerThread.java
│ │ │ ├── MosartRxFragment.java
│ │ │ ├── MosartRxPacketListAdapter.java
│ │ │ ├── MosartRxThread.java
│ │ │ ├── MosartScanFragment.java
│ │ │ ├── MosartScanThread.java
│ │ │ ├── MosartTabAdapter.java
│ │ │ ├── MosartTxFragment.java
│ │ │ ├── MosartTxPacketListAdapter.java
│ │ │ ├── MosartTxThread.java
│ │ │ └── MosartVisualizeDialogFragment.java
│ │ │ └── zigbee
│ │ │ ├── ZigbeeBus.java
│ │ │ ├── ZigbeeEditDialogFragment.java
│ │ │ ├── ZigbeeFragment.java
│ │ │ ├── ZigbeeRxFragment.java
│ │ │ ├── ZigbeeRxPacketListAdapter.java
│ │ │ ├── ZigbeeRxThread.java
│ │ │ ├── ZigbeeTabAdapter.java
│ │ │ ├── ZigbeeTxFragment.java
│ │ │ ├── ZigbeeTxPacketListAdapter.java
│ │ │ ├── ZigbeeTxThread.java
│ │ │ └── ZigbeeVisualizeDialogFragment.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── border.xml
│ │ ├── ic_add.xml
│ │ ├── ic_dashboard_black_24dp.xml
│ │ ├── ic_esb.xml
│ │ ├── ic_home_black_24dp.xml
│ │ ├── ic_keyboard_dev.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_mosart.xml
│ │ ├── ic_mosart2.xml
│ │ ├── ic_mouse_24.xml
│ │ ├── ic_mouse_dev.xml
│ │ ├── ic_notifications_black_24dp.xml
│ │ ├── ic_packet.xml
│ │ ├── ic_radiosploit.xml
│ │ ├── ic_unknown_dev.xml
│ │ └── ic_zigbee.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── chip_field_entry.xml
│ │ ├── fragment_edit_packet.xml
│ │ ├── fragment_esb.xml
│ │ ├── fragment_esb_rx.xml
│ │ ├── fragment_esb_scan.xml
│ │ ├── fragment_esb_tx.xml
│ │ ├── fragment_mosart.xml
│ │ ├── fragment_mosart_keylogger.xml
│ │ ├── fragment_mosart_rx.xml
│ │ ├── fragment_mosart_scan.xml
│ │ ├── fragment_mosart_tx.xml
│ │ ├── fragment_patch.xml
│ │ ├── fragment_visualize_packet.xml
│ │ ├── fragment_zigbee.xml
│ │ ├── fragment_zigbee_rx.xml
│ │ ├── fragment_zigbee_tx.xml
│ │ └── packet_view_item.xml
│ │ ├── menu
│ │ └── bottom_nav_menu.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── navigation
│ │ └── mobile_navigation.xml
│ │ ├── values-night
│ │ └── themes.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ └── test
│ └── java
│ └── laas
│ └── rcayre
│ └── radiosploit
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── radiosploit.apk
├── screenshots
├── esbrx.jpg
├── esbrx_small.jpg
├── esbtx.jpg
├── esbtx_small.jpg
├── mosartkeylogger.jpg
├── mosartkeylogger_small.jpg
├── mosartrx.jpg
├── mosartrx_small.jpg
├── mosartscan.jpg
├── mosartscan_small.jpg
├── zigbeedissector.jpg
├── zigbeedissector_small.jpg
├── zigbeerx.jpg
├── zigbeerx_small.jpg
├── zigbeetx.jpg
└── zigbeetx_small.jpg
└── settings.gradle
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Romain Cayre
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | RadioSploit 1.0
2 | ================
3 |
4 | This Android application allows to sniff and inject Zigbee, Mosart and Enhanced ShockBurst packets from a Samsung Galaxy S20 smartphone.
5 | It interacts with a set of patches installed on the phone Bluetooth controller, allowing to add new capabilities to communicate using the previously mentioned protocols.
6 |
7 | This project is a Proof of Concept developed in the context of a research work aiming at exploring the feasibility of cross-protocol pivoting attacks. If you need additional details, we have published multiple papers about it:
8 |
9 | * Romain Cayre, Florent Galtier, Guillaume Auriol, Vincent Nicomette, Mohamed Kaâniche, Géraldine Marconato. POSTER: Cross-protocol attacks : weaponizing a smartphone by diverting its Bluetooth controller. *14th ACM Conference on Security and Privacy in Wireless and Mobile Networks (WiSec 2021)*, Jun 2021, Abu Dhabi (virtual), UAE. **\[en\]**
10 |
11 | * Romain Cayre, Florent Galtier. [Attaques inter-protocolaires par détournement du contrôleur Bluetooth d'un téléphone mobile](https://hal.laas.fr/hal-03221148). *GT Sécurité des Systèmes, Logiciels et Réseaux*, May 2021, En ligne, France. **\[fr\]**
12 |
13 | * Romain Cayre, Florent Galtier, Guillaume Auriol, Vincent Nicomette, Mohamed Kaâniche, et al. [WazaBee: attacking Zigbee networks by diverting Bluetooth Low Energy chips](https://hal.laas.fr/hal-03193299). *IEEE/IFIP International Conference on Dependable Systems and Networks (DSN)*, Jun 2021, Taipei (virtual), Taiwan. **\[en\]**
14 |
15 | * Romain Cayre, Florent Galtier, Guillaume Auriol, Vincent Nicomette, Geraldine Marconato. [WazaBee : attaque de réseaux Zigbee par détournement de puces Bluetooth Low Energy](https://hal.laas.fr/hal-02778262). *Symposium sur la Sécurité des Technologies de l'Information et des Communications (SSTIC 2020)*, Jun 2020, Rennes, France. pp.381-418.**\[fr\]**
16 |
17 |
18 | This application is released as an opensource software using the MIT License.
19 |
20 | Screenshots
21 | ------------
22 | 
23 | 
24 | 
25 | 
26 | 
27 | 
28 | 
29 | 
30 |
31 | How to use this application ?
32 | ------------------------------
33 | * First, you need to root your Samsung Galaxy S20: it should also work on Samsung Galaxy S10, but it has not been tested yet. Multiple tutorials can be found online to enable root.
34 | * Enable the Bluetooth Debugging (BTsnoop logs) in your smartphone settings.
35 | * Then, you have to install the Radiosploit patches on your Bluetooth controller. The patches are uploaded on a different repository, follow [these instructions](https://github.com/RCayre/radiosploit_patches) !
36 | * Finally, you can install the application using adb:
37 | ```
38 | $ adb install radiosploit.apk
39 | ```
40 | * Launch the app and allow it to use root permissions.
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | compileSdkVersion 30
7 | buildToolsVersion "30.0.3"
8 |
9 | defaultConfig {
10 | applicationId "laas.rcayre.radiosploit"
11 | minSdkVersion 16
12 | targetSdkVersion 30
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_8
27 | targetCompatibility JavaVersion.VERSION_1_8
28 | }
29 | }
30 |
31 | dependencies {
32 |
33 | implementation 'androidx.appcompat:appcompat:1.2.0'
34 | implementation 'com.google.android.material:material:1.3.0'
35 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
36 | implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
37 | implementation 'androidx.navigation:navigation-fragment:2.3.5'
38 | implementation 'androidx.navigation:navigation-ui:2.3.5'
39 | implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
40 | implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
41 | implementation 'androidx.legacy:legacy-support-v4:1.0.0'
42 | implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
43 | implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
44 | testImplementation 'junit:junit:4.+'
45 | androidTestImplementation 'androidx.test.ext:junit:1.1.2'
46 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
47 |
48 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/MainActivity.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit;
2 |
3 | import android.os.Bundle;
4 |
5 | import com.example.radiosploit.R;
6 |
7 | import laas.rcayre.radiosploit.dissectors.Dissector;
8 |
9 | import com.google.android.material.bottomnavigation.BottomNavigationView;
10 |
11 | import androidx.appcompat.app.AppCompatActivity;
12 | import androidx.fragment.app.FragmentManager;
13 | import androidx.navigation.NavController;
14 | import androidx.navigation.Navigation;
15 | import androidx.navigation.ui.AppBarConfiguration;
16 | import androidx.navigation.ui.NavigationUI;
17 |
18 | public class MainActivity extends AppCompatActivity {
19 | /* This is the main activity. It instantiates the HCI interface and setup the views. */
20 | private HciInterface hciInterface = new HciInterface();
21 |
22 | public HciInterface getHciInterface() {
23 | /* Getter allowing to easily get HCI Interface instance */
24 | return hciInterface;
25 | }
26 |
27 | private void showPatchFragment() {
28 | /* This method shows a pop up indicating that the patches have not been found */
29 | FragmentManager fm = getSupportFragmentManager();
30 | PatchFragment patchFragment = PatchFragment.newInstance("Patches not found");
31 | patchFragment.show(fm, "PatchFragment");
32 |
33 | }
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 |
39 | // We configure the views / UI
40 | setContentView(R.layout.activity_main);
41 | BottomNavigationView navView = findViewById(R.id.nav_view);
42 | AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
43 | R.id.navigation_zigbee, R.id.navigation_mosart, R.id.navigation_esb)
44 | .build();
45 | NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
46 | NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
47 | NavigationUI.setupWithNavController(navView, navController);
48 |
49 | // We runs the HCI Interface thread (to extract HCI event)
50 | Thread hciInterfaceThread = new Thread(hciInterface);
51 | hciInterfaceThread.start();
52 |
53 | /*
54 | Here, we have to check that our patches are installed on the controller.
55 | We check if the string "RadioSploit" (in hex: 526164696F53706C6F6974) is present at address 0x2106cc in controller's RAM.
56 | If it is not, the patches are not installed, and we show a dialog to inform the user.
57 | */
58 | byte[] patchString = hciInterface.readRam(0x2106cc,11);
59 | if (!Dissector.bytesToHex(patchString).equals("526164696F53706C6F6974")) {
60 | this.showPatchFragment();
61 | }
62 |
63 |
64 | }
65 |
66 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/PacketItemData.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit;
2 |
3 | import com.example.radiosploit.R;
4 | import laas.rcayre.radiosploit.dissectors.Dissector;
5 |
6 | public class PacketItemData {
7 | /* This crappy class is used to represent a Packet or a Device */
8 | private byte[] content;
9 | private int imgId; // icon
10 | private int type;
11 | private String description;
12 | private String status;
13 |
14 | public PacketItemData(byte[] content, int type, String description,String status) {
15 | this.content = content;
16 | this.description = description;
17 | this.type = type;
18 | this.status = status;
19 | if (type == 0x01) {
20 | this.imgId = R.drawable.ic_zigbee;
21 | }
22 | else if (type == 0x02) {
23 | if (description.equals("Mouse")) {
24 | this.imgId = R.drawable.ic_mouse_dev;
25 | }
26 | else if (description.equals("Keyboard")) {
27 | this.imgId = R.drawable.ic_keyboard_dev;
28 | }
29 | else {
30 | this.imgId = R.drawable.ic_unknown_dev;
31 | }
32 | }
33 | else if (type == 0x04) {
34 | this.imgId = R.drawable.ic_packet;
35 | }
36 | else if (type == 0x05) {
37 | this.imgId = R.drawable.ic_unknown_dev;
38 | }
39 | else if (type == 0x06) {
40 | this.imgId = R.drawable.ic_packet;
41 | }
42 |
43 | else {
44 | this.imgId = R.drawable.ic_unknown_dev;
45 | }
46 | }
47 | public String getFormattedContent() {
48 | /* Getter allowing to get a Human readable version of the content */
49 | if (this.type != 0x02) {
50 | return Dissector.bytesToHex(content);
51 | }
52 | else return Dissector.bytesToAddress(content);
53 | }
54 |
55 | public String getDescription() {
56 | /* Getter allowing to get the description */
57 | return description;
58 | }
59 |
60 | public String getStatus() {
61 | /* Getter allowing to get the status */
62 | return status;
63 | }
64 |
65 | public int getType() {
66 | /* Getter allowing to get the type */
67 | return this.type;
68 | }
69 |
70 | public void setContent(byte[] content) {
71 | /* Setter allowing to modify the content */
72 | this.content = content;
73 | }
74 | public byte[] getContent() {
75 | /* Getter allowing to get the content (byte array) */
76 | return this.content;
77 | }
78 | public int getImgId() {
79 | /* Getter allowing to get the image identifier (used to choose the icon)*/
80 | return imgId;
81 | }
82 | public void update(PacketItemData newContent) {
83 | /* Method allowing to update the content of the current instance */
84 | this.content = newContent.getContent();
85 | this.description = newContent.getDescription();
86 | this.type = newContent.getType();
87 | this.imgId = newContent.getImgId();
88 | this.status = newContent.getStatus();
89 |
90 | }
91 | public void setStatus(String status) {
92 | /* Setter allowing to modify the status */
93 | this.status = status;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/PacketListAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.ImageView;
7 | import android.widget.RelativeLayout;
8 | import android.widget.TextView;
9 |
10 | import androidx.recyclerview.widget.RecyclerView;
11 |
12 | import com.example.radiosploit.R;
13 |
14 | import java.util.ArrayList;
15 |
16 | public abstract class PacketListAdapter extends RecyclerView.Adapter{
17 | /* Adapter allowing to manage a list of PacketItemData */
18 | private ArrayList packetList;
19 | public PacketListAdapter(ArrayList list) {
20 | this.packetList = list;
21 | }
22 |
23 | public abstract void onItemClick(View view,PacketItemData itemData, int position);
24 | public abstract void onItemLongClick(View view,PacketItemData itemData, int position);
25 |
26 | @Override
27 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
28 | LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
29 | View listItem= layoutInflater.inflate(R.layout.packet_view_item, parent, false);
30 | ViewHolder viewHolder = new ViewHolder(listItem);
31 | return viewHolder;
32 | }
33 |
34 | @Override
35 | public void onBindViewHolder(ViewHolder holder, int position) {
36 | final PacketItemData myListData = packetList.get(position);
37 | holder.descriptionTextView.setText("#"+String.valueOf(position)+" "+packetList.get(position).getDescription());
38 | holder.statusTextView.setText(packetList.get(position).getStatus());
39 | holder.contentTextView.setText(packetList.get(position).getFormattedContent());
40 | holder.imageView.setImageResource(packetList.get(position).getImgId());
41 |
42 | holder.relativeLayout.setOnClickListener(new View.OnClickListener() {
43 | @Override
44 | public void onClick(View view) {
45 | /* If there is a short click on a PacketItemData, propagate the event to the corresponding callback */
46 | PacketListAdapter.this.onItemClick(view,myListData, position);
47 | }
48 | });
49 | holder.relativeLayout.setOnLongClickListener(new View.OnLongClickListener() {
50 | @Override
51 | public boolean onLongClick (View view){
52 | /* If there is a long click on a PacketItemData, propagate the event to the corresponding callback */
53 | PacketListAdapter.this.onItemLongClick(view,myListData, position);
54 | return true;
55 | }
56 | }
57 | );
58 | }
59 |
60 |
61 | @Override
62 | public int getItemCount() {
63 | /* Returns the number of items in the list */
64 | return packetList.size();
65 | }
66 |
67 | public static class ViewHolder extends RecyclerView.ViewHolder {
68 | public ImageView imageView;
69 | public TextView descriptionTextView;
70 | public TextView statusTextView;
71 | public TextView contentTextView;
72 | public RelativeLayout relativeLayout;
73 | public ViewHolder(View itemView) {
74 | super(itemView);
75 | this.imageView = (ImageView) itemView.findViewById(R.id.packet_icon);
76 | this.descriptionTextView = (TextView) itemView.findViewById(R.id.packet_description);
77 | this.contentTextView = (TextView) itemView.findViewById(R.id.packet_content);
78 | this.statusTextView = (TextView) itemView.findViewById(R.id.packet_status);
79 | relativeLayout = (RelativeLayout)itemView.findViewById(R.id.packet_view_item_layout);
80 | }
81 | }
82 |
83 | /* Methods allowing to interact with the list items */
84 | public void addNewData(PacketItemData data){
85 | packetList.add(data);
86 | notifyDataSetChanged();
87 | }
88 |
89 | public void updateStatus(int packetId,String status) {
90 | packetList.get(packetId).setStatus(status);
91 | notifyItemChanged(packetId);
92 | }
93 | public void updateData(int packetId, PacketItemData data) {
94 | packetList.get(packetId).update(data);
95 | notifyItemChanged(packetId);
96 | }
97 |
98 | public void resetData() {
99 | packetList.clear();
100 | notifyDataSetChanged();
101 | }
102 |
103 | public PacketItemData getData(int position) {
104 | return packetList.get(position);
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/PatchFragment.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit;
2 |
3 |
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.Button;
9 |
10 | import androidx.fragment.app.DialogFragment;
11 |
12 | import com.example.radiosploit.R;
13 |
14 | public class PatchFragment extends DialogFragment {
15 | /* This Fragment is used to inform the user that he should install controller patches, nothing to see here */
16 | public static PatchFragment newInstance(String title) {
17 |
18 | PatchFragment frag = new PatchFragment();
19 | Bundle args = new Bundle();
20 | args.putString("title", title);
21 | frag.setArguments(args);
22 |
23 | return frag;
24 |
25 | }
26 |
27 | @Override
28 | public void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | }
31 |
32 | @Override
33 | public void onResume() {
34 | super.onResume();
35 | ViewGroup.LayoutParams params = getDialog().getWindow().getAttributes();
36 | params.width = android.view.WindowManager.LayoutParams.MATCH_PARENT;
37 | params.height = android.view.WindowManager.LayoutParams.WRAP_CONTENT;
38 |
39 | getDialog().getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
40 |
41 | }
42 |
43 | @Override
44 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
45 | View v = inflater.inflate(R.layout.fragment_patch, container, false);
46 | Button okButton = v.findViewById(R.id.patch_ok_button);
47 |
48 | // If we detect a click on the button, close the window
49 | okButton.setOnClickListener(new View.OnClickListener() {
50 | @Override
51 | public void onClick(View v) {
52 | dismiss();
53 | }
54 | });
55 | return v;
56 | }
57 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/dissectors/Dissector.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.dissectors;
2 |
3 | import java.util.ArrayList;
4 |
5 | public abstract class Dissector {
6 | /* This class implements a Protocol Dissector */
7 |
8 | public static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
9 | protected static final byte[] STOP_DISSECTION = {};
10 |
11 | public static String bytesToHex(byte[] bytes) {
12 | /* Converts bytes to an Hex string */
13 | char[] hexChars = new char[bytes.length * 2];
14 | for (int j = 0; j < bytes.length; j++) {
15 | int v = bytes[j] & 0xFF;
16 | hexChars[j * 2] = HEX_ARRAY[v >>> 4];
17 | hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
18 | }
19 | return new String(hexChars);
20 | }
21 | public static byte[] addressToBytes(String address) {
22 | /* Converts an address string ("11:22:33:44") to the correspond bytes */
23 | String addr = address.replace(":","");
24 | return hexToBytes(addr);
25 | }
26 |
27 | public static String bytesToAddress(byte[] bytes) {
28 | /* Converts bytes to an address string ("11:22:33:44") */
29 | String hex = bytesToHex(bytes);
30 | StringBuilder builder = new StringBuilder();
31 |
32 | int index = 0;
33 | while (index < hex.length())
34 | {
35 | builder.append(hex.substring(index,index+2));
36 |
37 | index += 2;
38 | if (index < hex.length()) builder.append(":");
39 | }
40 | return builder.toString();
41 | }
42 |
43 | public static byte[] hexToBytes(String s) {
44 | /*Converts an hex string to the corresponding bytes */
45 | int len = s.length();
46 |
47 | byte[] data = new byte[len / 2];
48 | for (int i = 0; i < len; i += 2) {
49 | data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
50 | + Character.digit(s.charAt(i+1), 16));
51 | }
52 | return data;
53 | }
54 | protected ArrayList fieldList;
55 | protected byte[] content;
56 |
57 | public Dissector(byte[] content) {
58 | this.content = content;
59 | this.fieldList = new ArrayList();
60 | }
61 | public Dissector(String content) {
62 | this.content = hexToBytes(content);
63 | this.fieldList = new ArrayList();
64 | }
65 | public void update(byte[] content) {
66 | this.content = content;
67 | }
68 |
69 | public void update(String content) {
70 | this.content = hexToBytes(content);
71 | }
72 | public ArrayList getFields() {
73 | return this.fieldList;
74 | }
75 | public abstract void dissect();
76 |
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbBus.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import laas.rcayre.radiosploit.PacketItemData;
4 |
5 | import io.reactivex.subjects.PublishSubject;
6 | import io.reactivex.Observable;
7 |
8 | public class EsbBus {
9 | /* This class is used to exchange information between two ESB fragments (RX > TX, used to add a received packet to the TX list) */
10 |
11 | /* Singleton implementation */
12 | private static EsbBus mInstance;
13 | public static EsbBus getInstance() {
14 | if (mInstance == null) {
15 | mInstance = new EsbBus();
16 | }
17 | return mInstance;
18 | }
19 | private EsbBus() {
20 | }
21 | private PublishSubject publisher = PublishSubject.create();
22 | void publish(PacketItemData packet) {
23 | publisher.onNext(packet);
24 | }
25 | Observable listen() {
26 | return publisher;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbDevice.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import laas.rcayre.radiosploit.dissectors.Dissector;
4 |
5 | public class EsbDevice {
6 | /* This class represents an Enhanced ShockBurst Device */
7 | private int channel;
8 | private String address;
9 |
10 | public EsbDevice(int channel, String address) {
11 | this.channel = channel;
12 | this.address = address;
13 | }
14 |
15 | public EsbDevice(int channel, byte[] address) {
16 | this.channel = channel;
17 | this.address = Dissector.bytesToAddress(address);
18 | }
19 |
20 | public int getChannel() {
21 | return this.channel;
22 | }
23 | public String getAddress() {
24 | return this.address;
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbDeviceBus.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import laas.rcayre.radiosploit.PacketItemData;
4 |
5 | import io.reactivex.subjects.PublishSubject;
6 | import io.reactivex.Observable;
7 |
8 | public class EsbDeviceBus {
9 | /* This class is used to exchange information between two ESB fragments (Scan > RX, used to automatically configure RX parameters based on the transmitted device) */
10 |
11 | /* Singleton implementation */
12 | private static EsbDeviceBus mInstance;
13 | public static EsbDeviceBus getInstance() {
14 | if (mInstance == null) {
15 | mInstance = new EsbDeviceBus();
16 | }
17 | return mInstance;
18 | }
19 | private EsbDeviceBus() {
20 | }
21 | private PublishSubject publisher = PublishSubject.create();
22 | void publish(PacketItemData packet) {
23 | publisher.onNext(packet);
24 | }
25 | // Listen should return an Observable
26 | Observable listen() {
27 | return publisher;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbDevicePacketListAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import android.view.View;
4 | import android.widget.Toast;
5 |
6 | import laas.rcayre.radiosploit.PacketItemData;
7 | import laas.rcayre.radiosploit.PacketListAdapter;
8 |
9 | import java.util.ArrayList;
10 |
11 | public class EsbDevicePacketListAdapter extends PacketListAdapter {
12 | /* Enhanced ShockBurst Device Packet List Adapter, represents a device PacketListData*/
13 | public EsbDevicePacketListAdapter(ArrayList list) {super(list);}
14 | @Override
15 | public void onItemClick(View view, PacketItemData itemData, int position) {
16 |
17 | }
18 |
19 | @Override
20 | public void onItemLongClick(View view, PacketItemData itemData, int position) {
21 | /* If a long click is detected on the device, automatically selects it in RX fragment */
22 | EsbDeviceBus.getInstance().publish(itemData);
23 | Toast.makeText(view.getContext(),"Address selected", Toast.LENGTH_LONG).show();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbDevicesList.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import laas.rcayre.radiosploit.MainActivity;
4 | import laas.rcayre.radiosploit.PacketItemData;
5 | import laas.rcayre.radiosploit.PacketListAdapter;
6 | import laas.rcayre.radiosploit.dissectors.Dissector;
7 |
8 | import java.util.ArrayList;
9 |
10 | public class EsbDevicesList {
11 | /* This class is a representation of a Enhanced ShockBurst Devices List*/
12 |
13 | private PacketListAdapter esbDeviceListAdapter ;
14 | private MainActivity activity;
15 | ArrayList deviceList = new ArrayList();
16 | public EsbDevicesList(MainActivity activity, PacketListAdapter adapter) {
17 | this.esbDeviceListAdapter = adapter;
18 | this.activity = activity;
19 | }
20 | public void clear() {
21 | /* This method clears the list */
22 | this.deviceList.clear();
23 | this.esbDeviceListAdapter.resetData();
24 | }
25 | public void addDevice(EsbDevice device) {
26 | /* This method allows to add a device if it is not already known */
27 | boolean found = false;
28 | for (int i=0;i packetList = new ArrayList();
63 | PacketListAdapter adapter = new EsbRxPacketListAdapter(packetList,this);
64 | esbRxPacketView.setHasFixedSize(true);
65 | esbRxPacketView.setLayoutManager(new LinearLayoutManager(root.getContext()));
66 | esbRxPacketView.setAdapter(adapter);
67 |
68 | EsbDeviceBus.getInstance().listen().subscribe(getInputObserver());
69 | esbRxThread = new EsbRxThread((MainActivity)getActivity(),adapter,hciInterface,esbRxPacketView);
70 |
71 | esbRxResetButton.setOnClickListener(new View.OnClickListener() {
72 | @Override
73 | public void onClick(View v) {
74 | adapter.resetData();
75 | }
76 | });
77 | esbRxChannelSlider.addOnChangeListener(new Slider.OnChangeListener() {
78 | @Override
79 | public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
80 | esbRxChannelLabel.setText("CH:" + String.valueOf((int) (value)));
81 | if (startRxToggleButton.isChecked() && esbRxAddress.getText().toString().length() == 14) {
82 | hciInterface.configureEsbRx(true,(int)value, Dissector.addressToBytes(esbRxAddress.getText().toString()));
83 | }
84 | }
85 | });
86 | startRxToggleButton.setOnClickListener(new View.OnClickListener() {
87 | @Override
88 | public void onClick(View arg0) {
89 | int channel = (int)(esbRxChannelSlider.getValue());
90 | if(startRxToggleButton.isChecked()){
91 | if (esbRxAddress.getText().toString().length() == 14) {
92 | hciInterface.configureEsbRx(true, channel, Dissector.addressToBytes(esbRxAddress.getText().toString()));
93 | }
94 | else {
95 | startRxToggleButton.setChecked(false);
96 | }
97 | Thread esbThread = new Thread(esbRxThread);
98 | esbThread.start();
99 | }
100 | else {
101 | byte[] address = {0x00,0x00,0x00,0x00,0x00};
102 | hciInterface.configureEsbRx(false,channel, address);
103 | esbRxThread.stop();
104 | }
105 | }});
106 |
107 | return root;
108 | }
109 | // Get input observer instance
110 | private Observer getInputObserver() {
111 | return new Observer() {
112 | @Override public void onSubscribe(Disposable d) {
113 | }
114 | @Override public void onNext(PacketItemData s) {
115 | int channel = Integer.parseInt(s.getStatus().substring(8,10));
116 | esbRxAddress.setText(s.getFormattedContent());
117 | esbRxChannelSlider.setValue(channel);
118 | esbRxChannelLabel.setText("CH: "+channel);
119 | }
120 | @Override public void onError(Throwable e) {
121 | }
122 | @Override public void onComplete() {
123 | }
124 | };
125 | }
126 |
127 | public void setUserVisibleHint(boolean visible) {
128 | super.setUserVisibleHint(visible);
129 | if (!visible) {
130 | /* If the fragment is hidden, stops the thread */
131 | if (esbRxThread != null && esbRxThread.isRunning()) {
132 | startRxToggleButton.setChecked(false);
133 | esbRxThread.stop();
134 | }
135 | }
136 | }
137 |
138 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbRxPacketListAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import android.view.View;
4 | import android.widget.Toast;
5 |
6 | import androidx.fragment.app.DialogFragment;
7 | import androidx.fragment.app.Fragment;
8 | import androidx.fragment.app.FragmentTransaction;
9 |
10 | import laas.rcayre.radiosploit.PacketItemData;
11 | import laas.rcayre.radiosploit.PacketListAdapter;
12 |
13 | import java.util.ArrayList;
14 |
15 | public class EsbRxPacketListAdapter extends PacketListAdapter {
16 | /* This class represents the packet list adapter for Enhanced Shockburst RX packets*/
17 | private Fragment rxFragment;
18 | public EsbRxPacketListAdapter(ArrayList list, Fragment rxFragment) {
19 | super(list);
20 | this.rxFragment = rxFragment;
21 | }
22 |
23 | public void onItemClick(View view, PacketItemData item, int position) {
24 | /* Short click : visualize the packet using EsbVisualizeDialogFragment */
25 | FragmentTransaction ft = this.rxFragment.getParentFragmentManager().beginTransaction();
26 | Fragment prev = this.rxFragment.getParentFragmentManager().findFragmentByTag("EsbVisualizeDialog");
27 | if (prev != null) {
28 | ft.remove(prev);
29 | }
30 | ft.addToBackStack(null);
31 | DialogFragment dialogFragment = EsbVisualizeDialogFragment.newInstance(item.getFormattedContent());
32 | dialogFragment.setTargetFragment(this.rxFragment,0);
33 | dialogFragment.show(ft, "EsbVisualizeDialog");
34 | }
35 | public void onItemLongClick(View view,PacketItemData item, int position) {
36 | /* Long click: transmit the packet to TX fragment using EsbBus */
37 | EsbBus.getInstance().publish(new PacketItemData(item.getContent(),0x06, item.getDescription(),""));
38 | Toast.makeText(view.getContext(),"Packet added to TX list", Toast.LENGTH_LONG).show();
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbRxThread.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import androidx.recyclerview.widget.RecyclerView;
4 |
5 | import laas.rcayre.radiosploit.HciInterface;
6 | import laas.rcayre.radiosploit.MainActivity;
7 | import laas.rcayre.radiosploit.PacketListAdapter;
8 | import laas.rcayre.radiosploit.PacketItemData;
9 |
10 | public class EsbRxThread implements Runnable {
11 | /* This class implements the Enhanced ShockBurst RX Thread, allowing to populates the RX packet list */
12 | private PacketListAdapter esbPacketListAdapter;
13 | private HciInterface hciInterface;
14 | private MainActivity activity;
15 | private RecyclerView packetView;
16 | private boolean running;
17 |
18 | public EsbRxThread(MainActivity activity, PacketListAdapter esbPacketListAdapter, HciInterface hciInterface,RecyclerView packetView) {
19 | this.esbPacketListAdapter = esbPacketListAdapter;
20 | this.hciInterface = hciInterface;
21 | this.activity = activity;
22 | this.packetView = packetView;
23 | }
24 |
25 | public boolean isRunning() {
26 | return running;
27 | }
28 |
29 | @Override
30 | public void run() {
31 | running = true;
32 | while (running) {
33 | PacketItemData packet = this.hciInterface.nextPacket();
34 |
35 | if (packet != null) {
36 | /* if we receive a packet ...*/
37 | activity.runOnUiThread(new Runnable() {
38 | @Override
39 | public void run() {
40 | // adds it to the list
41 | esbPacketListAdapter.addNewData(packet);
42 | // scrolls to the end of the list
43 | packetView.scrollToPosition(esbPacketListAdapter.getItemCount()-1);
44 | }
45 | });
46 |
47 |
48 | }
49 | }
50 | }
51 |
52 | public void stop() {
53 | running = false;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbScanFragment.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 |
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.Button;
9 | import android.widget.ProgressBar;
10 | import android.widget.ToggleButton;
11 |
12 | import androidx.fragment.app.Fragment;
13 | import androidx.recyclerview.widget.LinearLayoutManager;
14 | import androidx.recyclerview.widget.RecyclerView;
15 |
16 | import laas.rcayre.radiosploit.HciInterface;
17 | import laas.rcayre.radiosploit.MainActivity;
18 | import laas.rcayre.radiosploit.PacketItemData;
19 | import laas.rcayre.radiosploit.PacketListAdapter;
20 | import com.example.radiosploit.R;
21 |
22 | import java.util.ArrayList;
23 |
24 | public class EsbScanFragment extends Fragment {
25 | /* This is the Enhanced Shockburst Scan fragment, allowing to detect ESB devices */
26 | private EsbScanThread esbScanThread;
27 | private ToggleButton esbScanToggleButton;
28 | public EsbScanFragment() {
29 | }
30 |
31 | @Override
32 | public void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | }
35 |
36 | @Override
37 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
38 | Bundle savedInstanceState) {
39 |
40 | View root = inflater.inflate(R.layout.fragment_esb_scan, container, false);
41 | esbScanToggleButton = root.findViewById(R.id.esb_scan_toggle_button);
42 | RecyclerView deviceView = root.findViewById(R.id.esb_scan_device_view);
43 | ProgressBar progressBar = root.findViewById(R.id.esb_scan_progressbar);
44 | ArrayList packetList = new ArrayList();
45 | PacketListAdapter adapter = new EsbDevicePacketListAdapter(packetList);
46 | deviceView.setHasFixedSize(true);
47 | deviceView.setLayoutManager(new LinearLayoutManager(root.getContext()));
48 | deviceView.setAdapter(adapter);
49 |
50 | HciInterface hciInterface = ((MainActivity)getActivity()).getHciInterface();
51 | esbScanThread = new EsbScanThread((MainActivity)getActivity(),hciInterface,adapter, progressBar);
52 | Button esbScanResetButton = root.findViewById(R.id.esb_scan_reset_button);
53 | esbScanResetButton.setOnClickListener(new View.OnClickListener() {
54 | @Override
55 | public void onClick(View v) {
56 | esbScanThread.getDevicesList().clear();
57 | }
58 | });
59 |
60 | esbScanToggleButton.setOnClickListener(new View.OnClickListener() {
61 | @Override
62 | public void onClick(View arg0) {
63 | if(esbScanToggleButton.isChecked()){
64 | Thread esbThread = new Thread(esbScanThread);
65 | esbThread.start();
66 | }
67 | else {
68 | esbScanThread.stop();
69 | }
70 | }});
71 |
72 | return root;
73 | }
74 | public void setUserVisibleHint(boolean visible) {
75 | super.setUserVisibleHint(visible);
76 | if (!visible) {
77 | /* If the fragment is hidden, stops the thread */
78 | if (esbScanThread != null && esbScanThread.isRunning()) {
79 | esbScanToggleButton.setChecked(false);
80 | esbScanThread.stop();
81 | }
82 | }
83 | }
84 |
85 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbScanThread.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import android.widget.ProgressBar;
4 |
5 | import laas.rcayre.radiosploit.HciInterface;
6 | import laas.rcayre.radiosploit.MainActivity;
7 | import laas.rcayre.radiosploit.PacketItemData;
8 | import laas.rcayre.radiosploit.PacketListAdapter;
9 |
10 | import java.util.ArrayList;
11 | import java.util.HashMap;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | public class EsbScanThread implements Runnable {
16 | /* This is the thread allowing to scan Enhanced ShockBurst devices */
17 | private HciInterface hciInterface;
18 | private MainActivity activity;
19 | private ArrayList candidateAddressesList;
20 | private EsbDevicesList devicesList;
21 | private ProgressBar progressBar;
22 |
23 | private boolean running;
24 |
25 | public EsbScanThread(MainActivity activity, HciInterface hciInterface, PacketListAdapter adapter, ProgressBar progressBar) {
26 | this.hciInterface = hciInterface;
27 | this.activity = activity;
28 | this.devicesList = new EsbDevicesList(activity,adapter);
29 | this.candidateAddressesList = new ArrayList();
30 | this.progressBar = progressBar;
31 | }
32 |
33 | public EsbDevicesList getDevicesList() {
34 | return this.devicesList;
35 | }
36 | public boolean isRunning() {
37 | return running;
38 | }
39 |
40 | public static String mostCommon(List list) {
41 | /* This method returns the most common element in a list */
42 | Map map = new HashMap<>();
43 |
44 | for (String t : list) {
45 | Integer val = map.get(t);
46 | map.put(t, val == null ? 1 : val + 1);
47 | }
48 |
49 | Map.Entry max = null;
50 |
51 | for (Map.Entry e : map.entrySet()) {
52 | if (max == null || e.getValue() > max.getValue())
53 | max = e;
54 | }
55 |
56 | return max.getKey();
57 | }
58 | @Override
59 | public void run() {
60 | running = true;
61 | try {
62 | /* We explore every channel during 750 ms*/
63 | int channel = 2;
64 | this.progressBar.setMax(82);
65 | while (running) {
66 | this.hciInterface.configureEsbScan(true, channel);
67 | Thread.sleep(750);
68 | PacketItemData currentPacket;
69 | this.progressBar.setProgress(channel-2);
70 | candidateAddressesList.clear();
71 | do {
72 | currentPacket = this.hciInterface.nextPacket();
73 | if (currentPacket != null && !currentPacket.getDescription().equals("00:00:00:00:00")) {
74 | candidateAddressesList.add(currentPacket.getDescription());
75 | }
76 | } while(currentPacket != null);
77 | // If we received something, we wait 10 secs
78 | if (candidateAddressesList.size() != 0) {
79 | Thread.sleep(10000);
80 | do {
81 | currentPacket = this.hciInterface.nextPacket();
82 | if (currentPacket != null && !currentPacket.getDescription().equals("00:00:00:00:00")) {
83 | candidateAddressesList.add(currentPacket.getDescription());
84 | }
85 | } while(currentPacket != null);
86 |
87 | // We only keep the most common device because we may have false positives
88 | String winner = mostCommon(candidateAddressesList);
89 | devicesList.addDevice(channel,winner);
90 |
91 |
92 | }
93 | if (channel < 80) channel++;
94 | else channel = 2;
95 | }
96 | }
97 | catch (InterruptedException e) {
98 | running = false;
99 | }
100 | }
101 |
102 | public void stop() {
103 | running = false;
104 | }
105 | }
106 |
107 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbTabAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import androidx.annotation.Nullable;
4 | import androidx.fragment.app.Fragment;
5 | import androidx.fragment.app.FragmentManager;
6 | import androidx.fragment.app.FragmentPagerAdapter;
7 |
8 |
9 | public class EsbTabAdapter extends FragmentPagerAdapter {
10 | /* This class implements the EsbTabAdapter. We have three tabs: Scan (EsbScanFragment), RX (EsbRxFragment) and TX (EsbTxFragment)*/
11 |
12 | private String[] tabs_name = { "Scan", "RX", "TX" };
13 | public EsbTabAdapter(FragmentManager fm) {
14 | super(fm);
15 | }
16 | @Override
17 | public Fragment getItem(int index) {
18 |
19 | switch (index) {
20 | case 0:
21 | return new EsbScanFragment();
22 | case 1:
23 | return new EsbRxFragment();
24 | case 2:
25 | return new EsbTxFragment();
26 | }
27 |
28 | return null;
29 | }
30 | @Nullable
31 | @Override
32 | public CharSequence getPageTitle(int position) {
33 | return tabs_name[position];
34 | }
35 |
36 | @Override
37 | public int getCount() {
38 | return 3;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbTxPacketListAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 | import android.view.View;
4 |
5 | import androidx.fragment.app.DialogFragment;
6 | import androidx.fragment.app.Fragment;
7 | import androidx.fragment.app.FragmentTransaction;
8 |
9 | import laas.rcayre.radiosploit.PacketItemData;
10 | import laas.rcayre.radiosploit.PacketListAdapter;
11 |
12 | import java.util.ArrayList;
13 |
14 | public class EsbTxPacketListAdapter extends PacketListAdapter {
15 | /* This is the Enhanced Shockburst packet List Adapter, allowing to react to click events*/
16 | private EsbTxFragment txFragment;
17 | public EsbTxPacketListAdapter(ArrayList list, EsbTxFragment txFragment) {
18 | super(list);
19 | this.txFragment = txFragment;
20 | }
21 |
22 | public void onItemClick(View view, PacketItemData item, int position) {
23 | /* Short click, opens the edit dialog with the corresponding packet */
24 | FragmentTransaction ft = this.txFragment.getParentFragmentManager().beginTransaction();
25 | Fragment prev = this.txFragment.getParentFragmentManager().findFragmentByTag("EsbEditDialog");
26 | if (prev != null) {
27 | ft.remove(prev);
28 | }
29 | ft.addToBackStack(null);
30 | DialogFragment dialogFragment = EsbEditDialogFragment.newInstance(position,item.getFormattedContent());
31 | dialogFragment.setTargetFragment( this.txFragment,0);
32 | dialogFragment.show(ft, "EsbEditDialog");
33 |
34 | }
35 | public void onItemLongClick(View view,PacketItemData item, int position) {
36 | /* Long click, do nothing */
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/esb/EsbTxThread.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.esb;
2 |
3 |
4 | import android.widget.ProgressBar;
5 | import android.widget.TextView;
6 | import android.widget.ToggleButton;
7 |
8 | import laas.rcayre.radiosploit.HciInterface;
9 | import laas.rcayre.radiosploit.MainActivity;
10 | import laas.rcayre.radiosploit.PacketListAdapter;
11 | import laas.rcayre.radiosploit.dissectors.Dissector;
12 |
13 | public class EsbTxThread implements Runnable {
14 | /* This class implements the Enhanced ShockBurst TX Thread, allowing to transmit packets */
15 | private PacketListAdapter esbPacketListAdapter;
16 | private HciInterface hciInterface;
17 | private ProgressBar txProgressBar;
18 | private ToggleButton txToggleButton;
19 | private MainActivity mainActivity;
20 | private TextView addressEntry;
21 | private int channel;
22 |
23 | private boolean running;
24 |
25 | public EsbTxThread(MainActivity mainActivity,PacketListAdapter esbPacketListAdapter, HciInterface hciInterface, ProgressBar txProgressBar, ToggleButton txToggleButton, TextView addressEntry) {
26 | this.mainActivity = mainActivity;
27 | this.esbPacketListAdapter = esbPacketListAdapter;
28 | this.hciInterface = hciInterface;
29 | this.txProgressBar = txProgressBar;
30 | this.addressEntry = addressEntry;
31 | this.txToggleButton = txToggleButton;
32 | this.channel = 11;
33 | }
34 |
35 | public boolean isRunning() {
36 | return running;
37 | }
38 |
39 | public void updateChannel(int channel) {
40 | this.channel = channel;
41 | }
42 | @Override
43 | public void run() {
44 | /* For every packet in the list, we transmit it, then the thread is automatically stopped */
45 | running = true;
46 | for (int i=0;i fields = esbDissector.getFields();
58 | for (int i = 0; i < fields.size(); i++) {
59 | Chip newChip = (Chip) inflater.inflate(R.layout.chip_field_entry, chipGroup, false);
60 | newChip.setText(fields.get(i));
61 | newChip.setCloseIconVisible(false);
62 | newChip.setCheckedIconVisible(false);
63 | newChip.setCheckable(false);
64 | chipGroup.addView(newChip);
65 | scrollView.post(new Runnable() {
66 | public void run() {
67 | scrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
68 | }
69 | });
70 | }
71 | }
72 | @Override
73 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
74 | View v = inflater.inflate(R.layout.fragment_visualize_packet, container, false);
75 | packetContent = getArguments().getString("PacketData");
76 |
77 | ChipGroup chipGroup = v.findViewById(R.id.packet_visualizer_chipgroup);
78 | TextView packetData = v.findViewById(R.id.packet_visualizer_textentry);
79 | HorizontalScrollView scrollView = v.findViewById(R.id.packet_visualizer_fields_scrollview);
80 | Button closeButton = v.findViewById(R.id.packet_visualizer_close_button);
81 | EsbVisualizeDialogFragment currentFragment = this;
82 |
83 | packetData.setText(packetContent);
84 | closeButton.setOnClickListener(new View.OnClickListener() {
85 | @Override
86 | public void onClick(View view) {
87 | currentFragment.dismiss();
88 | }
89 | });
90 |
91 | Button addButton = v.findViewById(R.id.packet_visualizer_add_to_tx_button);
92 | addButton.setOnClickListener(new View.OnClickListener() {
93 | @Override
94 | public void onClick(View v) {
95 | String currentText = packetData.getText().toString();
96 | if (currentText.length() % 2 == 0) {
97 | /* Adds the packet to the TX list */
98 | byte[] esbFrame = Dissector.hexToBytes(currentText);
99 | String description = EsbDissector.extractPacketTypeFromFrame(esbFrame);
100 | if (description.equals("")) description = "Unknown packet";
101 | EsbBus.getInstance().publish(new PacketItemData(esbFrame,0x06, description,""));
102 | Toast.makeText(v.getContext(),"Packet added to TX list", Toast.LENGTH_LONG).show();
103 | currentFragment.dismiss();
104 | }
105 | }
106 | });
107 | EsbDissector esbDissector = new EsbDissector(packetData.getText().toString());
108 | updateDissectorView(chipGroup,esbDissector, inflater, scrollView, packetData.getText());
109 |
110 | return v;
111 | }
112 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartBus.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import laas.rcayre.radiosploit.PacketItemData;
4 |
5 | import io.reactivex.subjects.PublishSubject;
6 | import io.reactivex.Observable;
7 |
8 | public class MosartBus {
9 | /* This class is used to exchange information between two Mosart fragments (RX > TX, used to add a received packet to the TX list) */
10 |
11 | /* Singleton implementation */
12 | private static MosartBus mInstance;
13 | public static MosartBus getInstance() {
14 | if (mInstance == null) {
15 | mInstance = new MosartBus();
16 | }
17 | return mInstance;
18 | }
19 | private MosartBus() {
20 | }
21 | private PublishSubject publisher = PublishSubject.create();
22 |
23 | void publish(PacketItemData packet) {
24 | publisher.onNext(packet);
25 | }
26 | Observable listen() {
27 | return publisher;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartDevice.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import laas.rcayre.radiosploit.dissectors.MosartDissector;
4 |
5 | public class MosartDevice {
6 | /* This class represents a Mosart Device */
7 | private int channel;
8 | private String address;
9 | private String description;
10 | public MosartDevice(int channel, String address, String description) {
11 | this.channel = channel;
12 | this.address = address;
13 | this.description = description;
14 | }
15 |
16 | public MosartDevice(int channel, byte[] mosartFrame) {
17 | this.channel = channel;
18 | this.address = MosartDissector.extractAddressFromFrame(mosartFrame);
19 | this.description = MosartDissector.extractDeviceTypeFromFrame(mosartFrame);
20 | }
21 |
22 | public int getChannel() {
23 | return this.channel;
24 | }
25 | public String getDescription() {
26 | return this.description;
27 | }
28 |
29 | public String getAddress() {
30 | return this.address;
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartDeviceBus.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import laas.rcayre.radiosploit.PacketItemData;
4 |
5 | import io.reactivex.subjects.PublishSubject;
6 | import io.reactivex.Observable;
7 |
8 | public class MosartDeviceBus {
9 | /* This class is used to exchange information between two Zigbee fragments (Scan > RX / Keylogger, used to select a scanned device) */
10 |
11 | /* Singleton implementation */
12 | private static MosartDeviceBus mInstance;
13 | public static MosartDeviceBus getInstance() {
14 | if (mInstance == null) {
15 | mInstance = new MosartDeviceBus();
16 | }
17 | return mInstance;
18 | }
19 | private MosartDeviceBus() {
20 | }
21 | private PublishSubject publisher = PublishSubject.create();
22 |
23 | void publish(PacketItemData packet) {
24 | publisher.onNext(packet);
25 | }
26 | Observable listen() {
27 | return publisher;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartDevicePacketListAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import android.view.View;
4 | import android.widget.Toast;
5 |
6 | import laas.rcayre.radiosploit.PacketItemData;
7 | import laas.rcayre.radiosploit.PacketListAdapter;
8 |
9 | import java.util.ArrayList;
10 |
11 | public class MosartDevicePacketListAdapter extends PacketListAdapter {
12 | /* Mosart Device Packet List Adapter, represents a device PacketListData*/
13 | public MosartDevicePacketListAdapter(ArrayList list) {super(list);}
14 | @Override
15 | public void onItemClick(View view, PacketItemData itemData, int position) {
16 | }
17 |
18 | @Override
19 | public void onItemLongClick(View view, PacketItemData itemData, int position) {
20 | /* If a long click is detected on the device, automatically selects it in Keylogger / RX fragment */
21 | MosartDeviceBus.getInstance().publish(itemData);
22 | Toast.makeText(view.getContext(),"Address selected", Toast.LENGTH_LONG).show();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartDevicesList.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import laas.rcayre.radiosploit.MainActivity;
4 | import laas.rcayre.radiosploit.PacketItemData;
5 | import laas.rcayre.radiosploit.PacketListAdapter;
6 | import laas.rcayre.radiosploit.dissectors.Dissector;
7 |
8 | import java.util.ArrayList;
9 |
10 | public class MosartDevicesList {
11 | /* This class is a representation of a Mosart Devices List*/
12 | private PacketListAdapter mosartDeviceListAdapter;
13 | private MainActivity activity;
14 | ArrayList deviceList = new ArrayList();
15 | public MosartDevicesList(MainActivity activity, PacketListAdapter adapter) {
16 | this.mosartDeviceListAdapter = adapter;
17 | this.activity = activity;
18 | }
19 | public void clear() {
20 | /* This method clears the list */
21 | this.deviceList.clear();
22 | this.mosartDeviceListAdapter.resetData();
23 | }
24 | public void addDevice(MosartDevice device) {
25 | /* This method allows to add a device if it is not already known */
26 | boolean found = false;
27 | for (int i=0;i getInputObserver() {
104 | return new Observer() {
105 | @Override public void onSubscribe(Disposable d) {
106 | }
107 | @Override public void onNext(PacketItemData s) {
108 | int channel = Integer.parseInt(s.getStatus().substring(8,10));
109 | mosartKeyloggerAddress.setText(s.getFormattedContent());
110 | mosartKeyloggerChannelSlider.setValue(channel);
111 | mosartKeyloggerChannelLabel.setText("CH: "+channel);
112 | }
113 | @Override public void onError(Throwable e) {
114 | }
115 | @Override public void onComplete() {
116 | }
117 | };
118 | }
119 |
120 |
121 | public void setUserVisibleHint(boolean visible) {
122 | super.setUserVisibleHint(visible);
123 | if (!visible) {
124 | /* If the fragment is hidden, we have to stop the thread */
125 | if (mosartKeyloggerThread != null && mosartKeyloggerThread.isRunning()) {
126 | mosartKeyloggerThread.stop();
127 | byte[] address = {0x00, 0x00, 0x00, 0x00};
128 | hciInterface.configureMosartKeylogger(false, (int) (mosartKeyloggerChannelSlider.getValue()), address);
129 | startKeyloggerToggleButton.setChecked(false);
130 | }
131 | }
132 | }
133 |
134 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartKeyloggerThread.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import android.widget.EditText;
4 |
5 | import laas.rcayre.radiosploit.HciInterface;
6 | import laas.rcayre.radiosploit.MainActivity;
7 | import laas.rcayre.radiosploit.PacketItemData;
8 |
9 | public class MosartKeyloggerThread implements Runnable {
10 | /* This thread handles the keylogger packets and modify the Keystroke Visualizer */
11 | private HciInterface hciInterface;
12 | private MainActivity activity;
13 | private EditText visualizer;
14 | private boolean running;
15 |
16 | public MosartKeyloggerThread(MainActivity activity, HciInterface hciInterface,EditText visualizer) {
17 | this.hciInterface = hciInterface;
18 | this.activity = activity;
19 | this.visualizer = visualizer;
20 | }
21 |
22 | public boolean isRunning() {
23 | return running;
24 | }
25 | @Override
26 | public void run() {
27 | running = true;
28 | PacketItemData currentPacket;
29 |
30 | while (running) {
31 | currentPacket = this.hciInterface.nextPacket();
32 | if (currentPacket != null) {
33 | PacketItemData finalCurrentPacket = currentPacket;
34 | // When a keylogger packet is received, adds the corresponding key to the Keystroke Visualizer
35 | activity.runOnUiThread(
36 | new Runnable() {
37 | @Override
38 | public void run() {
39 | if (finalCurrentPacket.getDescription() != "*") { // Ignore key release
40 | visualizer.setText(visualizer.getText() + finalCurrentPacket.getDescription());
41 | }
42 | }
43 | }
44 | );
45 |
46 | }
47 | }
48 | }
49 |
50 | public void stop() {
51 | running = false;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartRxPacketListAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import android.view.View;
4 | import android.widget.Toast;
5 |
6 | import androidx.fragment.app.DialogFragment;
7 | import androidx.fragment.app.Fragment;
8 | import androidx.fragment.app.FragmentTransaction;
9 |
10 | import laas.rcayre.radiosploit.PacketItemData;
11 | import laas.rcayre.radiosploit.PacketListAdapter;
12 |
13 | import java.util.ArrayList;
14 |
15 | public class MosartRxPacketListAdapter extends PacketListAdapter {
16 | /* Mosart Rx Packet List adapter, allowing to react to click events */
17 | private Fragment rxFragment;
18 | public MosartRxPacketListAdapter(ArrayList list, Fragment rxFragment) {
19 | super(list);
20 | this.rxFragment = rxFragment;
21 | }
22 |
23 | public void onItemClick(View view, PacketItemData item, int position) {
24 | /* When a short click is detected, opens the visualizer with the corresponding packet */
25 | FragmentTransaction ft = this.rxFragment.getParentFragmentManager().beginTransaction();
26 | Fragment prev = this.rxFragment.getParentFragmentManager().findFragmentByTag("MosartVisualizeDialog");
27 | if (prev != null) {
28 | ft.remove(prev);
29 | }
30 | ft.addToBackStack(null);
31 | DialogFragment dialogFragment = MosartVisualizeDialogFragment.newInstance(item.getFormattedContent());
32 | dialogFragment.setTargetFragment(this.rxFragment,0);
33 | dialogFragment.show(ft, "MosartVisualizeDialog");
34 | }
35 | public void onItemLongClick(View view,PacketItemData item, int position) {
36 | /* When a long click is detected, transmits the packet to the TX fragment */
37 | MosartBus.getInstance().publish(new PacketItemData(item.getContent(),0x04, item.getDescription(),""));
38 | Toast.makeText(view.getContext(),"Packet added to TX list", Toast.LENGTH_LONG).show();
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartRxThread.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import androidx.recyclerview.widget.RecyclerView;
4 |
5 | import laas.rcayre.radiosploit.HciInterface;
6 | import laas.rcayre.radiosploit.MainActivity;
7 | import laas.rcayre.radiosploit.PacketListAdapter;
8 | import laas.rcayre.radiosploit.PacketItemData;
9 |
10 | public class MosartRxThread implements Runnable {
11 | /* Mosart RX Thread, receives Mosart packets and populates the packet's list */
12 | private PacketListAdapter mosartPacketListAdapter;
13 | private HciInterface hciInterface;
14 | private MainActivity activity;
15 | private RecyclerView packetView;
16 | private boolean running;
17 |
18 | public MosartRxThread(MainActivity activity, PacketListAdapter mosartPacketListAdapter, HciInterface hciInterface,RecyclerView packetView) {
19 | this.mosartPacketListAdapter = mosartPacketListAdapter;
20 | this.hciInterface = hciInterface;
21 | this.activity = activity;
22 | this.packetView = packetView;
23 | }
24 |
25 | public boolean isRunning() {
26 | return running;
27 | }
28 |
29 | @Override
30 | public void run() {
31 | running = true;
32 | while (running) {
33 | PacketItemData packet = this.hciInterface.nextPacket();
34 | /* When we receive a packet ... */
35 | if (packet != null) {
36 | activity.runOnUiThread(new Runnable() {
37 | @Override
38 | public void run() {
39 | // Adds it to the list
40 | mosartPacketListAdapter.addNewData(packet);
41 | // Scrolls to the last packet
42 | packetView.scrollToPosition(mosartPacketListAdapter.getItemCount()-1);
43 | }
44 | });
45 |
46 |
47 | }
48 | }
49 | }
50 |
51 | public void stop() {
52 | running = false;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartScanFragment.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 |
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.Button;
9 | import android.widget.ProgressBar;
10 | import android.widget.ToggleButton;
11 |
12 | import androidx.fragment.app.Fragment;
13 | import androidx.recyclerview.widget.LinearLayoutManager;
14 | import androidx.recyclerview.widget.RecyclerView;
15 |
16 | import laas.rcayre.radiosploit.HciInterface;
17 | import laas.rcayre.radiosploit.MainActivity;
18 | import laas.rcayre.radiosploit.PacketItemData;
19 | import laas.rcayre.radiosploit.PacketListAdapter;
20 | import com.example.radiosploit.R;
21 |
22 | import java.util.ArrayList;
23 |
24 | public class MosartScanFragment extends Fragment {
25 | /* This fragment allows to scan Mosart devices */
26 | private MosartScanThread mosartScanThread;
27 | private ToggleButton mosartScanToggleButton;
28 | public MosartScanFragment() {
29 | }
30 |
31 | @Override
32 | public void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | }
35 |
36 |
37 | @Override
38 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
39 | Bundle savedInstanceState) {
40 | /* Gets the views */
41 | View root = inflater.inflate(R.layout.fragment_mosart_scan, container, false);
42 | mosartScanToggleButton = root.findViewById(R.id.mosart_scan_toggle_button);
43 | RecyclerView deviceView = root.findViewById(R.id.mosart_scan_device_view);
44 | ProgressBar progressBar = root.findViewById(R.id.mosart_scan_progressbar);
45 | ArrayList packetList = new ArrayList();
46 | PacketListAdapter adapter = new MosartDevicePacketListAdapter(packetList);
47 | deviceView.setHasFixedSize(true);
48 | deviceView.setLayoutManager(new LinearLayoutManager(root.getContext()));
49 | deviceView.setAdapter(adapter);
50 |
51 | HciInterface hciInterface = ((MainActivity)getActivity()).getHciInterface();
52 | mosartScanThread = new MosartScanThread((MainActivity)getActivity(),hciInterface,adapter, progressBar);
53 | Button mosartScanResetButton = root.findViewById(R.id.mosart_scan_reset_button);
54 |
55 | /* Configures the listeners */
56 | mosartScanResetButton.setOnClickListener(new View.OnClickListener() {
57 | @Override
58 | public void onClick(View v) {
59 | mosartScanThread.getDevicesList().clear();
60 | }
61 | });
62 |
63 | mosartScanToggleButton.setOnClickListener(new View.OnClickListener() {
64 | @Override
65 | public void onClick(View arg0) {
66 | //int channel = (int)(zigbeeeChannelSlider.getValue());
67 | if(mosartScanToggleButton.isChecked()){
68 | Thread mosartThread = new Thread(mosartScanThread);
69 | mosartThread.start();
70 | }
71 | else {
72 | mosartScanThread.stop();
73 | }
74 | }});
75 |
76 | return root;
77 | }
78 | public void setUserVisibleHint(boolean visible) {
79 | super.setUserVisibleHint(visible);
80 | if (!visible) {
81 | /* When the fragment is hidden, stops the thread ! */
82 | if (mosartScanThread != null && mosartScanThread.isRunning()) {
83 | mosartScanToggleButton.setChecked(false);
84 | mosartScanThread.stop();
85 | }
86 | }
87 | }
88 |
89 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartScanThread.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import android.widget.ProgressBar;
4 |
5 | import laas.rcayre.radiosploit.HciInterface;
6 | import laas.rcayre.radiosploit.MainActivity;
7 | import laas.rcayre.radiosploit.PacketItemData;
8 | import laas.rcayre.radiosploit.PacketListAdapter;
9 | import laas.rcayre.radiosploit.dissectors.MosartDissector;
10 |
11 | public class MosartScanThread implements Runnable {
12 | /* This class implements the Mosart Scan thread */
13 | private HciInterface hciInterface;
14 | private MainActivity activity;
15 | private MosartDevicesList devicesList;
16 | private ProgressBar progressBar;
17 |
18 | private boolean running;
19 |
20 | public MosartScanThread(MainActivity activity, HciInterface hciInterface, PacketListAdapter adapter, ProgressBar progressBar) {
21 | this.hciInterface = hciInterface;
22 | this.activity = activity;
23 | this.devicesList = new MosartDevicesList(activity, adapter);
24 | this.progressBar = progressBar;
25 | }
26 |
27 | public boolean isRunning() {
28 | return running;
29 | }
30 |
31 | public MosartDevicesList getDevicesList() {
32 | return this.devicesList;
33 | }
34 | @Override
35 | public void run() {
36 | running = true;
37 | try {
38 | // Ok, ugly algorithm incoming.
39 |
40 | int channel = 2;
41 | this.progressBar.setMax(82);
42 | while (running) {
43 | // We explore every channel during 250ms, and we allow dongle frames (they are frequently transmitted)
44 | this.hciInterface.configureMosartScan(true, channel, true);
45 | Thread.sleep(250);
46 | PacketItemData currentPacket;
47 | this.progressBar.setProgress(channel-2);
48 | boolean dongleFound = false;
49 | do {
50 | currentPacket = this.hciInterface.nextPacket();
51 | if (currentPacket != null && MosartDissector.extractDeviceTypeFromFrame(currentPacket.getContent()).equals("Dongle")) {
52 | dongleFound = true;
53 | devicesList.addDevice(channel,currentPacket.getContent());
54 | }
55 | } while(currentPacket != null);
56 |
57 | // If we found dongle frames, it's probably an used channel :
58 | if (dongleFound) {
59 | // We stay on the same channel during 5 more seconds, but we ignore dongle frames
60 | this.hciInterface.configureMosartScan(true, channel, false);
61 | Thread.sleep(5000);
62 | do {
63 | currentPacket = this.hciInterface.nextPacket();
64 | if (currentPacket != null) {
65 | // If we found other devices here, we add them to the list
66 | devicesList.addDevice(channel,currentPacket.getContent());
67 | }
68 | } while(currentPacket != null);
69 |
70 | }
71 |
72 | if (channel < 80) channel++;
73 | else channel = 2;
74 | }
75 | }
76 | catch (InterruptedException e) {
77 | running = false;
78 | }
79 | }
80 |
81 | public void stop() {
82 | running = false;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartTabAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import androidx.annotation.Nullable;
4 | import androidx.fragment.app.Fragment;
5 | import androidx.fragment.app.FragmentManager;
6 | import androidx.fragment.app.FragmentPagerAdapter;
7 |
8 |
9 | public class MosartTabAdapter extends FragmentPagerAdapter {
10 | /* This class implements the MosartTabAdapter. We have four tabs: Scan (MosartScanFragment), KeyLogger (MosartKeyloggerFragment), RX (MosartRxFragment) and TX (MosartTxFragment)*/
11 | private String[] tabs_name = { "Scan", "Key logger", "RX", "TX" };
12 | public MosartTabAdapter(FragmentManager fm) {
13 | super(fm);
14 | }
15 | @Override
16 | public Fragment getItem(int index) {
17 |
18 | switch (index) {
19 | case 0:
20 | return new MosartScanFragment();
21 | case 1:
22 | return new MosartKeyloggerFragment();
23 | case 2:
24 | return new MosartRxFragment();
25 | case 3:
26 | return new MosartTxFragment();
27 | }
28 |
29 | return null;
30 | }
31 | @Nullable
32 | @Override
33 | public CharSequence getPageTitle(int position) {
34 | return tabs_name[position];
35 | }
36 |
37 | @Override
38 | public int getCount() {
39 | return 4;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartTxPacketListAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 | import android.view.View;
4 |
5 | import androidx.fragment.app.DialogFragment;
6 | import androidx.fragment.app.Fragment;
7 | import androidx.fragment.app.FragmentTransaction;
8 |
9 | import laas.rcayre.radiosploit.PacketItemData;
10 | import laas.rcayre.radiosploit.PacketListAdapter;
11 |
12 | import java.util.ArrayList;
13 |
14 | public class MosartTxPacketListAdapter extends PacketListAdapter {
15 | /* This class implements Mosart Tx Packet List Adapter, allowing to react to click events */
16 | private MosartTxFragment txFragment;
17 | public MosartTxPacketListAdapter(ArrayList list, MosartTxFragment txFragment) {
18 | super(list);
19 | this.txFragment = txFragment;
20 | }
21 |
22 | public void onItemClick(View view, PacketItemData item, int position) {
23 | /* A short click is detected, opens an editor dialog */
24 | FragmentTransaction ft = this.txFragment.getParentFragmentManager().beginTransaction();
25 | Fragment prev = this.txFragment.getParentFragmentManager().findFragmentByTag("MosartEditDialog");
26 | if (prev != null) {
27 | ft.remove(prev);
28 | }
29 | ft.addToBackStack(null);
30 | DialogFragment dialogFragment = MosartEditDialogFragment.newInstance(position,item.getFormattedContent());
31 | dialogFragment.setTargetFragment( this.txFragment,0);
32 | dialogFragment.show(ft, "MosartEditDialog");
33 |
34 | }
35 | public void onItemLongClick(View view,PacketItemData item, int position) {
36 |
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/mosart/MosartTxThread.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.mosart;
2 |
3 |
4 | import android.widget.ProgressBar;
5 | import android.widget.ToggleButton;
6 |
7 | import laas.rcayre.radiosploit.HciInterface;
8 | import laas.rcayre.radiosploit.MainActivity;
9 | import laas.rcayre.radiosploit.PacketListAdapter;
10 |
11 | public class MosartTxThread implements Runnable {
12 | /* This class implements the Mosart TX Thread*/
13 | private PacketListAdapter mosartPacketListAdapter;
14 | private HciInterface hciInterface;
15 | private ProgressBar txProgressBar;
16 | private ToggleButton txToggleButton;
17 | private MainActivity mainActivity;
18 | private int channel;
19 |
20 | private boolean running;
21 |
22 | public MosartTxThread(MainActivity mainActivity,PacketListAdapter mosartPacketListAdapter, HciInterface hciInterface, ProgressBar txProgressBar, ToggleButton txToggleButton) {
23 | this.mainActivity = mainActivity;
24 | this.mosartPacketListAdapter = mosartPacketListAdapter;
25 | this.hciInterface = hciInterface;
26 | this.txProgressBar = txProgressBar;
27 | this.txToggleButton = txToggleButton;
28 | this.channel = 11;
29 | }
30 |
31 | public boolean isRunning() {
32 | return running;
33 | }
34 |
35 | public void updateChannel(int channel) {
36 | this.channel = channel;
37 | }
38 | @Override
39 | public void run() {
40 | /* Transmits every packets present in the list, then stops the thread */
41 | running = true;
42 | for (int i=0;i fields = mosartDissector.getFields();
59 | for (int i = 0; i < fields.size(); i++) {
60 | Chip newChip = (Chip) inflater.inflate(R.layout.chip_field_entry, chipGroup, false);
61 | newChip.setText(fields.get(i));
62 | newChip.setCloseIconVisible(false);
63 | newChip.setCheckedIconVisible(false);
64 | newChip.setCheckable(false);
65 | chipGroup.addView(newChip);
66 | scrollView.post(new Runnable() {
67 | public void run() {
68 | scrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
69 | }
70 | });
71 | }
72 | }
73 | @Override
74 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
75 | View v = inflater.inflate(R.layout.fragment_visualize_packet, container, false);
76 | packetContent = getArguments().getString("PacketData");
77 |
78 | ChipGroup chipGroup = v.findViewById(R.id.packet_visualizer_chipgroup);
79 | TextView packetData = v.findViewById(R.id.packet_visualizer_textentry);
80 | HorizontalScrollView scrollView = v.findViewById(R.id.packet_visualizer_fields_scrollview);
81 | Button closeButton = v.findViewById(R.id.packet_visualizer_close_button);
82 | MosartVisualizeDialogFragment currentFragment = this;
83 |
84 | packetData.setText(packetContent);
85 | closeButton.setOnClickListener(new View.OnClickListener() {
86 | @Override
87 | public void onClick(View view) {
88 | currentFragment.dismiss();
89 | }
90 | });
91 |
92 | Button addButton = v.findViewById(R.id.packet_visualizer_add_to_tx_button);
93 | addButton.setOnClickListener(new View.OnClickListener() {
94 | @Override
95 | public void onClick(View v) {
96 | String currentText = packetData.getText().toString();
97 | if (currentText.length() % 2 == 0) {
98 | byte[] mosartFrame = Dissector.hexToBytes(currentText);
99 | MosartBus.getInstance().publish(new PacketItemData(mosartFrame,0x04, (mosartFrame.length > 2 ? MosartDissector.extractPacketTypeFromFrame(Arrays.copyOfRange(mosartFrame,2,mosartFrame.length)) : "Unknown packet"),""));
100 | Toast.makeText(v.getContext(),"Packet added to TX list", Toast.LENGTH_LONG).show();
101 | currentFragment.dismiss();
102 | }
103 | }
104 | });
105 | MosartDissector mosartDissector = new MosartDissector(packetData.getText().toString());
106 | updateDissectorView(chipGroup,mosartDissector, inflater, scrollView, packetData.getText());
107 |
108 | return v;
109 | }
110 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/zigbee/ZigbeeBus.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.zigbee;
2 |
3 | import laas.rcayre.radiosploit.PacketItemData;
4 |
5 | import io.reactivex.subjects.PublishSubject;
6 | import io.reactivex.Observable;
7 |
8 | public class ZigbeeBus {
9 | /* This class is used to exchange information between two Zigbee fragments (RX > TX, used to add a received packet to the TX list) */
10 |
11 | /* Singleton implementation */
12 | private static ZigbeeBus mInstance;
13 | public static ZigbeeBus getInstance() {
14 | if (mInstance == null) {
15 | mInstance = new ZigbeeBus();
16 | }
17 | return mInstance;
18 | }
19 | private ZigbeeBus() {
20 | }
21 |
22 |
23 | private PublishSubject publisher = PublishSubject.create();
24 |
25 | void publish(PacketItemData packet) {
26 | /* Publish a packet */
27 | publisher.onNext(packet);
28 | }
29 |
30 |
31 | Observable listen() {
32 | /* Returns an Observable */
33 | return publisher;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/zigbee/ZigbeeFragment.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.zigbee;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import androidx.annotation.NonNull;
9 | import androidx.fragment.app.Fragment;
10 | import androidx.viewpager.widget.ViewPager;
11 |
12 | import com.example.radiosploit.R;
13 | import com.google.android.material.tabs.TabLayout;
14 |
15 | public class ZigbeeFragment extends Fragment {
16 | /* Zigbee Fragment, it mainly instantiates the tabs */
17 | public View onCreateView(@NonNull LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {
18 | View root = inflater.inflate(R.layout.fragment_zigbee, container, false);
19 | ZigbeeTabAdapter tabAdapter = new ZigbeeTabAdapter(getChildFragmentManager());
20 | ViewPager viewPager = root.findViewById(R.id.zigbee_view_pager);
21 | viewPager.setAdapter(tabAdapter);
22 | TabLayout tabs = root.findViewById(R.id.zigbee_tabs);
23 | tabs.setupWithViewPager(viewPager);
24 | return root;
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/zigbee/ZigbeeRxFragment.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.zigbee;
2 |
3 | import android.os.Bundle;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.fragment.app.Fragment;
7 | import androidx.recyclerview.widget.LinearLayoutManager;
8 | import androidx.recyclerview.widget.RecyclerView;
9 |
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.Button;
14 | import android.widget.CompoundButton;
15 | import android.widget.Switch;
16 | import android.widget.TextView;
17 | import android.widget.ToggleButton;
18 |
19 | import laas.rcayre.radiosploit.HciInterface;
20 | import laas.rcayre.radiosploit.MainActivity;
21 | import laas.rcayre.radiosploit.PacketListAdapter;
22 | import com.example.radiosploit.R;
23 | import laas.rcayre.radiosploit.PacketItemData;
24 | import com.google.android.material.slider.Slider;
25 |
26 | import java.util.ArrayList;
27 |
28 | public class ZigbeeRxFragment extends Fragment {
29 | /* Zigbee RX Fragment, used to receive Zigbee packets */
30 | private ZigbeeRxThread zigbeeRxThread;
31 | private Slider zigbeeChannelSlider;
32 | private HciInterface hciInterface;
33 | private ToggleButton startRxToggleButton;
34 | public ZigbeeRxFragment() {
35 | }
36 |
37 | @Override
38 | public void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | }
41 |
42 |
43 | @Override
44 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
45 | Bundle savedInstanceState) {
46 |
47 | View root = inflater.inflate(R.layout.fragment_zigbee_rx, container, false);
48 | zigbeeChannelSlider = (Slider)(root.findViewById(R.id.zigbee_channel_slider));
49 | TextView zigbeeChannelLabel = (TextView) (root.findViewById(R.id.zigbee_channel_label));
50 | startRxToggleButton = (ToggleButton) root.findViewById(R.id.zigbee_rx_toggle_button);
51 | Button zigbeeResetButton = root.findViewById(R.id.zigbee_reset_button);
52 | Switch zigbeeFcsSwitch = root.findViewById(R.id.zigbee_fcs_check);
53 | RecyclerView packetView = root.findViewById(R.id.zigbee_rx_packet_view);
54 |
55 | hciInterface = ((MainActivity)getActivity()).getHciInterface();
56 |
57 | zigbeeChannelSlider.addOnChangeListener(new Slider.OnChangeListener() {
58 | @Override
59 | public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
60 | zigbeeChannelLabel.setText("CH:" + String.valueOf((int) (value)));
61 | if (startRxToggleButton.isChecked()) {
62 | hciInterface.configureZigbeeRx(true,(int)value);
63 | }
64 | }
65 |
66 | });
67 | ArrayList packetList = new ArrayList();
68 | PacketListAdapter adapter = new ZigbeeRxPacketListAdapter(packetList,this);
69 | packetView.setHasFixedSize(true);
70 | packetView.setLayoutManager(new LinearLayoutManager(root.getContext()));
71 | packetView.setAdapter(adapter);
72 |
73 |
74 | zigbeeRxThread = new ZigbeeRxThread((MainActivity)getActivity(),adapter,hciInterface,zigbeeFcsSwitch.isChecked(),packetView);
75 | startRxToggleButton.setOnClickListener(new View.OnClickListener() {
76 | @Override
77 | public void onClick(View arg0) {
78 | int channel = (int)(zigbeeChannelSlider.getValue());
79 | if(startRxToggleButton.isChecked()){
80 | hciInterface.configureZigbeeRx(true,channel);
81 | Thread zigbeeThread = new Thread(zigbeeRxThread);
82 | zigbeeThread.start();
83 | }
84 | else {
85 | hciInterface.configureZigbeeRx(false,channel);
86 | zigbeeRxThread.stop();
87 | }
88 | }});
89 | zigbeeResetButton.setOnClickListener(new View.OnClickListener() {
90 | @Override
91 | public void onClick(View arg0) {
92 | adapter.resetData();
93 | }
94 | });
95 |
96 | zigbeeFcsSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
97 | @Override
98 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
99 | zigbeeRxThread.updateCheckFCS(isChecked);
100 | }
101 | });
102 |
103 | return root;
104 |
105 | }
106 | public void setUserVisibleHint(boolean visible) {
107 | super.setUserVisibleHint(visible);
108 | if (!visible) {
109 | /* If the fragment is hidden, we have to stop the thread if it is running */
110 | if (zigbeeRxThread != null && zigbeeRxThread.isRunning()) {
111 | int channel = (int)(zigbeeChannelSlider.getValue());
112 | hciInterface.configureZigbeeRx(false,channel);
113 | startRxToggleButton.setChecked(false);
114 | zigbeeRxThread.stop();
115 | }
116 | }
117 | }
118 | }
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/zigbee/ZigbeeRxPacketListAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.zigbee;
2 |
3 | import android.view.View;
4 | import android.widget.Toast;
5 |
6 | import androidx.fragment.app.DialogFragment;
7 | import androidx.fragment.app.Fragment;
8 | import androidx.fragment.app.FragmentTransaction;
9 |
10 | import laas.rcayre.radiosploit.PacketItemData;
11 | import laas.rcayre.radiosploit.PacketListAdapter;
12 |
13 | import java.util.ArrayList;
14 |
15 | public class ZigbeeRxPacketListAdapter extends PacketListAdapter {
16 | /* Zigbee RX packet list adapter */
17 | private Fragment rxFragment;
18 | public ZigbeeRxPacketListAdapter(ArrayList list, Fragment rxFragment) {
19 | super(list);
20 | this.rxFragment = rxFragment;
21 | }
22 |
23 | public void onItemClick(View view, PacketItemData item, int position) {
24 | /* If a short click is detected, opens the packet in the Visualizer */
25 | FragmentTransaction ft = this.rxFragment.getParentFragmentManager().beginTransaction();
26 | Fragment prev = this.rxFragment.getParentFragmentManager().findFragmentByTag("ZigbeeVisualizeDialog");
27 | if (prev != null) {
28 | ft.remove(prev);
29 | }
30 | ft.addToBackStack(null);
31 | DialogFragment dialogFragment = ZigbeeVisualizeDialogFragment.newInstance(item.getFormattedContent());
32 | dialogFragment.setTargetFragment(this.rxFragment,0);
33 | dialogFragment.show(ft, "ZigbeeVisualizeDialog");
34 | }
35 | public void onItemLongClick(View view,PacketItemData item, int position) {
36 | /* If a long click is detected, add the packet to the TX list */
37 | ZigbeeBus.getInstance().publish(new PacketItemData(item.getContent(),0x01, item.getDescription(),""));
38 | Toast.makeText(view.getContext(),"Packet added to TX list", Toast.LENGTH_LONG).show();
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/zigbee/ZigbeeRxThread.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.zigbee;
2 |
3 | import androidx.recyclerview.widget.RecyclerView;
4 |
5 | import laas.rcayre.radiosploit.HciInterface;
6 | import laas.rcayre.radiosploit.MainActivity;
7 | import laas.rcayre.radiosploit.PacketListAdapter;
8 | import laas.rcayre.radiosploit.PacketItemData;
9 | import laas.rcayre.radiosploit.dissectors.ZigbeeDissector;
10 |
11 | public class ZigbeeRxThread implements Runnable {
12 | /* Zigbee RX thread, allowing to get the packets from the HCI Interface and add it to the list */
13 | private PacketListAdapter zigbeePacketListAdapter;
14 | private HciInterface hciInterface;
15 | private MainActivity activity;
16 | private RecyclerView packetView;
17 | private boolean checkFCS;
18 | private boolean running;
19 |
20 | public ZigbeeRxThread(MainActivity activity, PacketListAdapter zigbeePacketListAdapter, HciInterface hciInterface,boolean checkFCS,RecyclerView packetView) {
21 | this.zigbeePacketListAdapter = zigbeePacketListAdapter;
22 | this.hciInterface = hciInterface;
23 | this.activity = activity;
24 | this.checkFCS = checkFCS;
25 | this.packetView = packetView;
26 | }
27 |
28 | public boolean isRunning() {
29 | return running;
30 | }
31 |
32 | public void updateCheckFCS(boolean checkFCS) {
33 | this.checkFCS = checkFCS;
34 | }
35 | @Override
36 | public void run() {
37 | running = true;
38 | while (running) {
39 | /* While the thread is running, get packets, check the FCS if needed and add it to the packet list */
40 | PacketItemData packet = this.hciInterface.nextPacket();
41 |
42 | if (packet != null && (!this.checkFCS || (this.checkFCS && ZigbeeDissector.checkCrc(packet.getContent())))) {
43 | activity.runOnUiThread(new Runnable() {
44 | @Override
45 | public void run() {
46 | // Add the packet
47 | zigbeePacketListAdapter.addNewData(packet);
48 | // Scroll to the last packet
49 | packetView.scrollToPosition(zigbeePacketListAdapter.getItemCount()-1);
50 | }
51 | });
52 |
53 |
54 | }
55 | }
56 | }
57 |
58 | public void stop() {
59 | running = false;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/zigbee/ZigbeeTabAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.zigbee;
2 |
3 | import androidx.annotation.Nullable;
4 | import androidx.fragment.app.Fragment;
5 | import androidx.fragment.app.FragmentManager;
6 | import androidx.fragment.app.FragmentPagerAdapter;
7 |
8 | public class ZigbeeTabAdapter extends FragmentPagerAdapter {
9 | /* Zigbee Tab Adapter, it exposes two tabs, Receive (ZigbeeRxFragment) and Transmit (ZigbeeTxFragment) */
10 | private String[] tabs_name = { "Receive", "Transmit" };
11 | public ZigbeeTabAdapter(FragmentManager fm) {
12 | super(fm);
13 | }
14 | @Override
15 | public Fragment getItem(int index) {
16 | switch (index) {
17 | case 0:
18 | return new ZigbeeRxFragment();
19 | case 1:
20 | return new ZigbeeTxFragment();
21 | }
22 |
23 | return null;
24 | }
25 |
26 | @Nullable
27 | @Override
28 | public CharSequence getPageTitle(int position) {
29 | return tabs_name[position];
30 | }
31 |
32 | @Override
33 | public int getCount() {
34 | return 2;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/zigbee/ZigbeeTxPacketListAdapter.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.zigbee;
2 |
3 | import android.view.View;
4 |
5 | import androidx.fragment.app.DialogFragment;
6 | import androidx.fragment.app.Fragment;
7 | import androidx.fragment.app.FragmentTransaction;
8 |
9 | import laas.rcayre.radiosploit.PacketItemData;
10 | import laas.rcayre.radiosploit.PacketListAdapter;
11 |
12 | import java.util.ArrayList;
13 |
14 | public class ZigbeeTxPacketListAdapter extends PacketListAdapter {
15 | /* Zigbee TX Packet List Adapter */
16 | private ZigbeeTxFragment txFragment;
17 | public ZigbeeTxPacketListAdapter(ArrayList list, ZigbeeTxFragment txFragment) {
18 | super(list);
19 | this.txFragment = txFragment;
20 | }
21 |
22 | public void onItemClick(View view, PacketItemData item, int position) {
23 | /* If there's a short click, open the packet in the editor view */
24 | FragmentTransaction ft = this.txFragment.getParentFragmentManager().beginTransaction();
25 | Fragment prev = this.txFragment.getParentFragmentManager().findFragmentByTag("ZigbeeEditDialog");
26 | if (prev != null) {
27 | ft.remove(prev);
28 | }
29 | ft.addToBackStack(null);
30 | DialogFragment dialogFragment = ZigbeeEditDialogFragment.newInstance(position,item.getFormattedContent());
31 | dialogFragment.setTargetFragment( this.txFragment,0);
32 | dialogFragment.show(ft, "ZigbeeEditDialog");
33 |
34 | }
35 | public void onItemLongClick(View view,PacketItemData item, int position) {
36 |
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/java/laas/rcayre/radiosploit/ui/zigbee/ZigbeeTxThread.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit.ui.zigbee;
2 |
3 |
4 | import android.widget.ProgressBar;
5 | import android.widget.ToggleButton;
6 |
7 | import laas.rcayre.radiosploit.HciInterface;
8 | import laas.rcayre.radiosploit.MainActivity;
9 | import laas.rcayre.radiosploit.PacketListAdapter;
10 |
11 | public class ZigbeeTxThread implements Runnable {
12 | /* Zigbee TX thread, used to transmit Zigbee packets */
13 | private PacketListAdapter zigbeePacketListAdapter;
14 | private HciInterface hciInterface;
15 | private ProgressBar txProgressBar;
16 | private ToggleButton txToggleButton;
17 | private MainActivity mainActivity;
18 | private int channel;
19 |
20 | private boolean running;
21 |
22 | public ZigbeeTxThread(MainActivity mainActivity,PacketListAdapter zigbeePacketListAdapter, HciInterface hciInterface, ProgressBar txProgressBar, ToggleButton txToggleButton) {
23 | this.mainActivity = mainActivity;
24 | this.zigbeePacketListAdapter = zigbeePacketListAdapter;
25 | this.hciInterface = hciInterface;
26 | this.txProgressBar = txProgressBar;
27 | this.txToggleButton = txToggleButton;
28 | this.channel = 11;
29 | }
30 |
31 | public boolean isRunning() {
32 | return running;
33 | }
34 |
35 | public void updateChannel(int channel) {
36 | this.channel = channel;
37 | }
38 | @Override
39 | public void run() {
40 | running = true;
41 | for (int i=0;i fields = zigbeeDissector.getFields();
57 | for (int i = 0; i < fields.size(); i++) {
58 | Chip newChip = (Chip) inflater.inflate(R.layout.chip_field_entry, chipGroup, false);
59 | newChip.setText(fields.get(i));
60 | newChip.setCloseIconVisible(false);
61 | newChip.setCheckedIconVisible(false);
62 | newChip.setCheckable(false);
63 | chipGroup.addView(newChip);
64 | scrollView.post(new Runnable() {
65 | public void run() {
66 | scrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
67 | }
68 | });
69 | }
70 | }
71 | @Override
72 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
73 | View v = inflater.inflate(R.layout.fragment_visualize_packet, container, false);
74 |
75 | /* We get the parameters transmitted to the fragment */
76 | packetContent = getArguments().getString("PacketData");
77 |
78 | /* Views initialization */
79 | ChipGroup chipGroup = v.findViewById(R.id.packet_visualizer_chipgroup);
80 | TextView packetData = v.findViewById(R.id.packet_visualizer_textentry);
81 | HorizontalScrollView scrollView = v.findViewById(R.id.packet_visualizer_fields_scrollview);
82 | Button closeButton = v.findViewById(R.id.packet_visualizer_close_button);
83 | ZigbeeVisualizeDialogFragment currentFragment = this;
84 |
85 | /* Updates packet content */
86 | packetData.setText(packetContent);
87 |
88 | /* Manage events */
89 | closeButton.setOnClickListener(new View.OnClickListener() {
90 | @Override
91 | public void onClick(View view) {
92 | currentFragment.dismiss();
93 | }
94 | });
95 |
96 | Button addButton = v.findViewById(R.id.packet_visualizer_add_to_tx_button);
97 | addButton.setOnClickListener(new View.OnClickListener() {
98 | @Override
99 | public void onClick(View v) {
100 | String currentText = packetData.getText().toString();
101 | if (currentText.length() % 2 == 0) {
102 | ZigbeeBus.getInstance().publish(new PacketItemData(Dissector.hexToBytes(currentText),0x01, ZigbeeDissector.getZigbeePacketDescription(Dissector.hexToBytes(currentText)),""));
103 | Toast.makeText(v.getContext(),"Packet added to TX list", Toast.LENGTH_LONG).show();
104 | currentFragment.dismiss();
105 | }
106 | }
107 | });
108 | ZigbeeDissector zigbeeDissector = new ZigbeeDissector(packetData.getText().toString());
109 | updateDissectorView(chipGroup,zigbeeDissector, inflater, scrollView, packetData.getText());
110 |
111 | return v;
112 | }
113 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/border.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dashboard_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_esb.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
30 |
33 |
36 |
39 |
42 |
45 |
48 |
51 |
54 |
55 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_keyboard_dev.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mosart.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mosart2.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mouse_24.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mouse_dev.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_notifications_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_packet.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_radiosploit.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
30 |
33 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_unknown_dev.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_zigbee.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/chip_field_entry.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_edit_packet.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
20 |
21 |
28 |
29 |
36 |
37 |
38 |
45 |
46 |
50 |
56 |
57 |
58 |
61 |
62 |
69 |
70 |
77 |
78 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_esb.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
11 |
16 |
17 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_esb_rx.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
14 |
15 |
21 |
22 |
32 |
33 |
39 |
40 |
48 |
49 |
50 |
51 |
55 |
56 |
65 |
66 |
67 |
78 |
79 |
80 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_esb_scan.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
17 |
18 |
24 |
25 |
31 |
32 |
41 |
42 |
43 |
44 |
45 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_esb_tx.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
18 |
19 |
30 |
31 |
39 |
40 |
50 |
51 |
57 |
58 |
64 |
65 |
74 |
75 |
76 |
77 |
83 |
84 |
93 |
94 |
105 |
106 |
107 |
108 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_mosart.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
11 |
16 |
17 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_mosart_keylogger.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
14 |
15 |
21 |
22 |
31 |
32 |
38 |
39 |
47 |
48 |
49 |
50 |
54 |
55 |
64 |
65 |
66 |
77 |
78 |
79 |
80 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_mosart_rx.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
14 |
15 |
21 |
22 |
31 |
32 |
38 |
39 |
47 |
48 |
49 |
50 |
54 |
55 |
64 |
65 |
66 |
77 |
78 |
79 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_mosart_scan.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
17 |
18 |
24 |
25 |
31 |
32 |
41 |
42 |
43 |
44 |
45 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_mosart_tx.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
17 |
18 |
28 |
29 |
35 |
36 |
42 |
43 |
52 |
53 |
54 |
55 |
61 |
62 |
71 |
72 |
83 |
84 |
85 |
86 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_patch.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
23 |
24 |
33 |
34 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_visualize_packet.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
20 |
21 |
28 |
29 |
36 |
37 |
38 |
47 |
48 |
52 |
58 |
59 |
60 |
63 |
64 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_zigbee.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
11 |
16 |
17 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_zigbee_rx.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
29 |
30 |
39 |
40 |
41 |
42 |
46 |
47 |
56 |
57 |
68 |
69 |
70 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_zigbee_tx.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
17 |
18 |
28 |
29 |
35 |
36 |
42 |
43 |
52 |
53 |
54 |
55 |
61 |
62 |
71 |
72 |
83 |
84 |
85 |
86 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/packet_view_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
17 |
18 |
29 |
38 |
39 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/bottom_nav_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/navigation/mobile_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
20 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RadioSploit
3 | Zigbee
4 | Mosart
5 | Enhanced ShockBurst
6 |
7 | Hello blank fragment
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/test/java/laas/rcayre/radiosploit/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package laas.rcayre.radiosploit;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:4.1.3"
9 | // NOTE: Do not place your application dependencies here; they belong
10 | // in the individual module build.gradle files
11 | }
12 | }
13 | allprojects {
14 | repositories {
15 | google()
16 | jcenter()
17 | }
18 | }
19 |
20 | task clean(type: Delete) {
21 | delete rootProject.buildDir
22 | }
23 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu May 13 19:30:06 CEST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/radiosploit.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/radiosploit.apk
--------------------------------------------------------------------------------
/screenshots/esbrx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/esbrx.jpg
--------------------------------------------------------------------------------
/screenshots/esbrx_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/esbrx_small.jpg
--------------------------------------------------------------------------------
/screenshots/esbtx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/esbtx.jpg
--------------------------------------------------------------------------------
/screenshots/esbtx_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/esbtx_small.jpg
--------------------------------------------------------------------------------
/screenshots/mosartkeylogger.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/mosartkeylogger.jpg
--------------------------------------------------------------------------------
/screenshots/mosartkeylogger_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/mosartkeylogger_small.jpg
--------------------------------------------------------------------------------
/screenshots/mosartrx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/mosartrx.jpg
--------------------------------------------------------------------------------
/screenshots/mosartrx_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/mosartrx_small.jpg
--------------------------------------------------------------------------------
/screenshots/mosartscan.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/mosartscan.jpg
--------------------------------------------------------------------------------
/screenshots/mosartscan_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/mosartscan_small.jpg
--------------------------------------------------------------------------------
/screenshots/zigbeedissector.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/zigbeedissector.jpg
--------------------------------------------------------------------------------
/screenshots/zigbeedissector_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/zigbeedissector_small.jpg
--------------------------------------------------------------------------------
/screenshots/zigbeerx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/zigbeerx.jpg
--------------------------------------------------------------------------------
/screenshots/zigbeerx_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/zigbeerx_small.jpg
--------------------------------------------------------------------------------
/screenshots/zigbeetx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/zigbeetx.jpg
--------------------------------------------------------------------------------
/screenshots/zigbeetx_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RCayre/radiosploit/5fb78aaf706e9336d96fed232fb54bfd490d94d9/screenshots/zigbeetx_small.jpg
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | rootProject.name = "RadioSploit"
--------------------------------------------------------------------------------