Saturday, January 7, 2017

Alexa Enabled Terrarium Temperature Monitor

I recently acquired a Hogg Island boa constrictor. An important part about keeping these types of snakes is maintaining a temperature gradient across the enclosure so the snake can thermoregulate. I had a couple TTF-103 thermistors laying around so I thought it would be cool to set up a temperature monitoring system.


I decided to use the Arduino Yun I had on hand to collect the data and make it available on the internet. A quick Google search for "TTF-103 arduino" and I found some code to convert the readings from the thermistor to temperature. I added some code to log readings from two thermistors to the SD card on the Linux side of the Yun.

    File dataFile = FileSystem.open("/mnt/sd/temperature.log", FILE_APPEND);
    if (dataFile) {
         dataFile.println(getTimeStamp()+","+String(ADCPin)+","+String(fTemp,4));
         dataFile.close();

  }




I put the Yun in a Radio Shack project box and attached it to the back of the snake's enclosure with velcro.

I used regular old scotch tape to attach the thermistors inside the enclosure.



Initially I created a page using jpgraph that displays the temperature readings of both sides of the enclosure .

This was working fine, but wouldn't it be cool if I could just ask the terrarium what the temperature was like? Enter Alexa. It was actually easier than I thought to get a custom skill up and running using the Amazon documentation. The biggest issue I had was trying to get Amazon to use a page served from the web server on the Yun. No matter what I did it complained about the security of the SSL certificate I was using. I ended up finding an Amazon Lambda function that acts as a proxy to bypass this security requirement. All that was left was writing a quick page to return the temperature readings in a format that Alexa can understand.

<?php
exec("tail -n 2 /mnt/sd/temperature.log",$lines);
$left = explode(',',$lines[0]);
$right = explode(',',$lines[1]);
$readings = array('left'=>$left[2],'right'=>$right[2]);

$outputSpeech = array("type"=>"PlainText","text"=>"Left side temp ".$readings['left'] ." degrees. Right side temp ".$readings['right'] ." degrees");
$card = array("content"=>"Left: ".$readings['left']." F\nRight: ".$readings['right']." F","title"=>"Temp Readings","type"=>"Simple");
$response = array("version"=>"1.0","response"=>array("outputSpeech"=>$outputSpeech,"card"=>$card,"shouldEndSession"=>true));
header('Content-Type: application/json');
echo json_encode($response,JSON_PRETTY_PRINT);

?>

This produces JSON like this:
{
    "version": "1.0",
    "response": {
        "outputSpeech": {
            "type": "PlainText",
            "text": "Left side temp 76.5225 degrees. Right side temp 81.8562 degrees"
        },
        "card": {
            "content": "Left: 76.5225 F\nRight: 81.8562 F",
            "title": "Temp Readings",
            "type": "Simple"
        },
        "shouldEndSession": true
    }
}




How to Get Free Gogo In Air Internet

On my flight to Phoenix I was having trouble making a decision on wether or not to pay for in air internet access.  I knew I wouldn't be on long but did want to check emails. While I was trying to make up my mind, I browsed the selection of movies offered by Gogo. I decided to rent The Intern and was prompted to download the newest Gogo movie player. When I clicked the link, I was presented with a captcha before being forwarded to the App store. The thought occurred to me that it was probably not limiting access to Apple servers. I fired up Chrome and sure enough I could browse the net and check my email. The unrestricted access lasted about 15 minutes, but it was all I needed at the time.  Throughout the 5 hour flight I was able to use this trick 2 more times for a total access time of around 45 minutes.

Thursday, May 26, 2016

[SPOILER] How I completed the Google Firebass Challenge (but not in time to win a ticket to IO17)

[SPOILER ALERT**** THIS WILL SHOW YOU THE CLUES TO COMPLETE THE CHALLENGE]

At the conclusion of Google IO this year, Firebase launched a challenge to follow digital clues for a shot at a free ticket to IO17 next year. I ultimately solved the puzzle although it was a little too late. I was not in the first 100 so no ticket for me.

Here is how I did it:

I was pointed to the start of the challenge from a twitter post pointing to https://firebase.foo.

This was a faux version of https://firebase.google.com. The gist is that someone mistyped firebase as firebass and has unleashed a time traveling bass on the internet!

Anyone familiar with html should be able to spot the problematic link that looks like it is sending you to an admin interface. Some playing around eventually led me to replace firebase with firebass. That brought me to a login page.

Inspecting the elements on this page I found two things: the image name and alt text were
 <img alt="01101000011001110111011101100101011011000110110001110011" src="../../images/01101000011001110111011101100101011011000110110001110011.png">

and the action on the login form had an error in it about an invalid character in author name.

Pasting the binary value in an online binary to ascii converter yielded the text hgwells. Adding that to the broken link got me to https://probassfinders.foo/home/hgwells.html.

Aside from some distractions like a web based terminal, the obvious next step here is a My Account link in the upper left. Following this link takes you to another login page with a cool ascii art image of a bass. If you pay attention, you will see some hex numbers that are a different color. If you take the highlighted hex numbers and convert them to ascii they spell "Members and Affiliates of the Intergalactic Computer Network". Weird! A quick Google search leads to a paper by J.C.R Licklider (who is an interesting fellow in his own right). But what to do with this clue? Some more digging and I noticed the title of the page looked like it was base64 encoded: Li4vLi4vYmFzcy9qY3IqKioqKioqKiouaHRtbA== which decodes to ../../bass/jcr*********.html. Aha! https://probassfinders.foo/bass/jcrlicklider.html

Hmmmm, 64 boxes with two possible states? A little javascript to generate a string of 1's and 0's and back to the binary to ascii converter: blp.html.

At this point there was originally a timer counting down and the terminal displayed an error message with the path to a log file. The log file is a base64 encoded png.

The dialog in the fake terminal gave me the clue as to what to do here. It mentioned a delta. The png consisted of transparent pixels and black pixels. I duplicated it as a layer in gimp and started shifting it around. A shift (or delta) of 111 pixels horizontally exposed some text. A vertical shift cleared up the overlapping pattern to reveal what appeared to be mv firebass. Thanks to some fellow bass hunters on twitter who were much better at image manipulation it was revealed to be mv firebass firebase.

After the timer expired, a time portal page was displayed.


Now at this point I did take the easy way out. While working out the individual clues, including tracking down the coordinates in the animated gif, someone posted the solution URL to twitter. Oh well, I'll take it I thought. So off I went to https://probassfinders.foo/walleyejournal/SILO.html.

This was another page with a timer where I had to wait a couple days. Once the timer ran out, it was another time portal page with a new url. There was also the base64 encoded image disguised as a log file. Shifting it as before reveals another clue. The file may be resistant, use the --force.

The next page was a 90's style fanclub page. It was similar to the last set of clues in that you had to navigate the site to find numbered clues and string them together to form a url. The interesting clue on this round was an icon that looked like it was supposed to play a wav file. Searching the code a bit revealed some actual Firebase code referencing a wav file called spectrogram.wav. 

     console.log('TODO: Complete connection to Firebase Storage'); var storageRef = firebase.app().storage().ref(); var file = storageRef.child('spectrogram.wav'); // TODO: Get download URL for file (https://developers.google.com/firebase/docs/storage/web/download-files)

In the javascript console, running file.getDownloadURL(); returns an object containing the direct download link for the wav file.

I downloaded a free Spectrogram generator called Spek. Opening the wav file yielded
So along with the easy clues, the whole url ended up being https://probassfinders.foo/000147/notafish/MOODMUSIC/Alex/FIN/index.html.

This ended up being the final page.

This time the terminal was actually usable. It was a text based game that should be pretty easy to work out without going through each one. Suffice to say that the end culminates with you using mv firebass firebase --force.

And there you go, you captured the firebass!










Thursday, February 4, 2016

We Need a Fry's Electronics in Pittsburgh

I was in Phoenix recently for business and thought I would pop in to the local Fry's Electronics. Being from San Diego, I miss being able to run into Fry's to pick up parts that I now have to order on line. Not only did they have the selection of computer parts and electronic components I remember, they had entire isles dedicated to Arduino and prototyping as well as drones in all shapes and sizes.
Why don't we have a place like this in the 'burgh? You can even pick up a pair of handcuffs!

Friday, January 8, 2016

Hacking the XYZ Davinci Jr. Part 2

In my previous post I explained how I was able to capture the passwords for the NFC chips on my XYZ Davinci Jr. In this post I will share some Arduino code I used to read the password protected data, where the remaining length data is, and how to write to the chip.

I started by trying to work through the PN512 chip on the printer itself. I connected the Arduino and could write to the FIFO on the PN512, but could not get it to execute the transceive command. I opted to purchase the PN532 shield from Adafruit. The library for working with the shield is on GitHub here, however it does not support password authentication of NTAG213 cards.  I started working on adding a method to the library for authenticating but was trying to use the wrong communication mode. Thanks to use dcorovia on the Adafruit forums, I was able to authenticate using the following addition to the Adafruit library:

byte Adafruit_PN532::NFC_PWD_AUTH(byte *pwd){
byte result;
#if DEBUG_NFC_PWD_AUTH
Serial.print(F("NFC_PWD_AUTH : "));
#endif
/* Prepare the command */
pn532_packetbuffer[0] = PN532_COMMAND_INCOMMUNICATETHRU;
pn532_packetbuffer[1] = 0x1B; 
memcpy (pn532_packetbuffer+2, pwd, 4); // 4 bytes or 32 bit password.

/* Send the command */

result=sendCommandCheckAck(pn532_packetbuffer, 2+4);
#if DEBUG_NFC_PWD_AUTH
Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 40);
#endif 
if (!result)
{
#if DEBUG_NFC_PWD_AUTH
Serial.println(F("Failed to receive ACK for NFC_PWD_AUTH"));
#endif
return 0;
}
/* Read the response packet 8 + 4 */
readdata(pn532_packetbuffer, 12);
#if DEBUG_NFC_PWD_AUTH
Adafruit_PN532::PrintHexChar(pn532_packetbuffer, 12);
#endif
if (pn532_packetbuffer[7] == 0x00)
{
// response is 00 00 FF 05 FB D5 43 00 00 00 E8 00
pwd[0] = pn532_packetbuffer[8];
pwd[1] = pn532_packetbuffer[9];
}
else
{
// Is pwd is wrong we get 00 00 FF 03 FD D5 43 01 E7 00
// Byte 8 is 01
#if DEBUG_NFC_PWD_AUTH
Serial.println(F("Unexpected response NFC_PWD_AUTH: "));
#endif
return 0;

return 1;
}

With a small modification to the NTAG213 example included with the Adafruit library, I was able to authenticate and read the protected pages of memory:

      byte pwd[] = {0x22, 0x66, 0x52, 0xC6};
      //byte pwd[] = {0x93, 0x1B, 0x18, 0x0C};
      //byte pwd[] = {0x75, 0x9A, 0x67, 0x0D};
      nfc.NFC_PWD_AUTH(pwd);
     // nfc.ntag2xx_Authenticate(pwd);
      for (uint8_t i = 0; i < 42; i++) 
      {
        success = nfc.ntag2xx_ReadPage(i, data);
        
        // Display the current page number
        Serial.print("PAGE ");
        if (i < 10)
        {
          Serial.print("0");
          Serial.print(i);
        }
        else
        {
          Serial.print(i);
        }
        Serial.print(": ");

        // Display the results, depending on 'success'

        if (success) 
        {
          // Dump the page data
          nfc.PrintHexChar(data, 4);
        }
        else
        {
          Serial.println("Unable to read the requested page!");
        }

 See this post for the memory contents. 

I posted the contents to SoliForum. We could see that some of the pages remained unchanged when compared after running a part, but some changed. We knew the changing pages must have the length encoded and  SoliForum user ChunkLady realized they were stored in little-endian (right to left). ChunkLady pointed out that page 10 never changed and was 1000000 in decimal. Page 20 was 82347. This corresponded to 100 meters (original length) and 82 meters (remaining length as reported by the printer itself.

The other pages that change are 21,22, and 23. The function of these pages still needs to be identified. They do have something to do with verifying the remaining length information. When I tried to write just to the remaining length (Page 20), the printer complained that the spool was unrecognized. After writing all the original information back to the chip, the printer accepted it and reported the original remaining length. So the key to the current state here is to capture the state of the chip preferably when it is new and then reset the chip to the known state when you load a roll of 3rd party filament.

Writing to the pages was simple using the Adafruit library:

      byte spoolLen[]={0xAB, 0x41, 0x01, 0x00};
      byte page21[]={0xE3, 0x53, 0x33, 0x54};
      byte page22[]={0x25, 0x4D, 0xE1, 0xCE};
      byte page23[]={0xBF, 0xBC, 0x49, 0x76};
      nfc.ntag2xx_WritePage(20,spoolLen);
      nfc.ntag2xx_WritePage(21,page21);
      nfc.ntag2xx_WritePage(22,page22);
      nfc.ntag2xx_WritePage(23,page23);

I hope this information helps and maybe we can get some more eyes on the remaining problems like cracking the password on the chips so they do not need to be captured with hardware and the function of the other memory pages. It would also be cool to get something working with the on-board PN512 to read and write to the chips without having to have an additional shield.

Thursday, January 7, 2016

JunkBot

Here is a bot I made from some stuff I had lying around. It is kind of a typical RC car platform with an Arduino Uno. I had picked up a few Unos and Seeed Motor Shields at some Radio Shack clearance sales.



The "eyes" are a Parallax Ping ultrasound sensor from the same Radio Shack sale.




Right now it just backs up when it detects something within 5 inches of the ultrasound device.

XYZ NFC Chip Passwords

Here are the authenticated dumps from a few XYZ spools:

UID Value: 0x04 0x38 0xDC 0x22 0x9A 0x3D 0x81
PWD: 0x22 0x66 0x52 0xC6  
PAGE 00: 04 38 DC 68  .8�h
PAGE 01: 22 9A 3D 81  "�=�
PAGE 02: 04 48 00 00  .H..
PAGE 03: E1 10 12 00  �...
PAGE 04: 01 03 A0 0C  ..�.
PAGE 05: 34 03 00 FE  4..�
PAGE 06: 00 00 00 00  ....
PAGE 07: 00 00 00 00  ....
PAGE 08: 5A 50 5A 00  ZPZ.
PAGE 09: 00 35 35 36  .556
PAGE 10: A0 86 01 00  ��..
PAGE 11: A0 86 01 00  ��..
PAGE 12: D2 00 2D 00  �.-.
PAGE 13: 54 48 47 42  THGB
PAGE 14: 30 34 37 39  0479
PAGE 15: 00 00 00 00  ....
PAGE 16: 00 00 00 00  ....
PAGE 17: 34 00 00 00  4...
PAGE 18: 00 00 00 00  ....
PAGE 19: 00 00 00 00  ....
PAGE 20: AB 41 01 00  �A..
PAGE 21: E3 53 33 54  �S3T
PAGE 22: 25 4D E1 CE  %M��
PAGE 23: BF BC 49 76  ��Iv
PAGE 24: 00 00 00 00  ....
PAGE 25: 00 00 00 00  ....
PAGE 26: 00 00 00 00  ....
PAGE 27: 00 00 00 00  ....
PAGE 28: 00 00 00 00  ....
PAGE 29: 00 00 00 00  ....
PAGE 30: 00 00 00 00  ....
PAGE 31: 00 00 00 00  ....
PAGE 32: 00 00 00 00  ....
PAGE 33: 00 00 00 00  ....
PAGE 34: 00 00 00 00  ....
PAGE 35: 00 00 00 00  ....
PAGE 36: 00 00 00 00  ....
PAGE 37: 00 00 00 00  ....
PAGE 38: 00 00 00 00  ....
PAGE 39: 00 00 00 00  ....
PAGE 40: 00 00 00 BD  ...�
PAGE 41: 07 00 00 08  ....

UID Value: 0x04 0x20 0x57 0x22 0x97 0x3C 0x80
PWD: 0x93 0x1B 0x18 0x0C
PAGE 00: 04 20 57 FB  . W�
PAGE 01: 22 97 3C 80  "�<�
PAGE 02: 09 48 00 00  .H..
PAGE 03: E1 10 12 00  �...
PAGE 04: 01 03 A0 0C  ..�.
PAGE 05: 34 03 00 FE  4..�
PAGE 06: 00 00 00 00  ....
PAGE 07: 00 00 00 00  ....
PAGE 08: 5A 50 50 00  ZPP.
PAGE 09: 00 35 34 54  .54T
PAGE 10: 40 0D 03 00  @...
PAGE 11: 40 0D 03 00  @...
PAGE 12: D2 00 2D 00  �.-.
PAGE 13: 54 48 47 42  THGB
PAGE 14: 30 34 39 35  0495
PAGE 15: 00 00 00 00  ....
PAGE 16: 00 00 00 00  ....
PAGE 17: 34 00 00 00  4...
PAGE 18: 00 00 00 00  ....
PAGE 19: 00 00 00 00  ....
PAGE 20: 40 0D 03 00  @...
PAGE 21: 08 1F 31 54  ..1T
PAGE 22: 50 B1 E0 CE  P���
PAGE 23: 52 E7 4F 76  R�Ov
PAGE 24: 00 00 00 00  ....
PAGE 25: 00 00 00 00  ....
PAGE 26: 00 00 00 00  ....
PAGE 27: 00 00 00 00  ....
PAGE 28: 00 00 00 00  ....
PAGE 29: 00 00 00 00  ....
PAGE 30: 00 00 00 00  ....
PAGE 31: 00 00 00 00  ....
PAGE 32: 00 00 00 00  ....
PAGE 33: 00 00 00 00  ....
PAGE 34: 00 00 00 00  ....
PAGE 35: 00 00 00 00  ....
PAGE 36: 00 00 00 00  ....
PAGE 37: 00 00 00 00  ....
PAGE 38: 00 00 00 00  ....
PAGE 39: 00 00 00 00  ....
PAGE 40: 00 00 00 BD  ...�
PAGE 41: 07 00 00 08  ....

UID Value: 0x04 0x4F 0x57 0x22 0x97 0x3C 0x80
PWD: 0x75 0x9A 0x67 0x0D
PAGE 00: 04 4F 57 94  .OW�
PAGE 01: 22 97 3C 80  "�<�
PAGE 02: 09 48 00 00  .H..
PAGE 03: E1 10 12 00  �...
PAGE 04: 01 03 A0 0C  ..�.
PAGE 05: 34 03 00 FE  4..�
PAGE 06: 00 00 00 00  ....
PAGE 07: 00 00 00 00  ....
PAGE 08: 5A 50 50 00  ZPP.
PAGE 09: 00 35 34 54  .54T
PAGE 10: 40 0D 03 00  @...
PAGE 11: 40 0D 03 00  @...
PAGE 12: D2 00 2D 00  �.-.
PAGE 13: 54 48 47 42  THGB
PAGE 14: 30 31 32 33  0123
PAGE 15: 00 00 00 00  ....
PAGE 16: 00 00 00 00  ....
PAGE 17: 34 00 00 00  4...
PAGE 18: 00 00 00 00  ....
PAGE 19: 00 00 00 00  ....
PAGE 20: 40 0D 03 00  @...
PAGE 21: 08 1F 31 54  ..1T
PAGE 22: 50 B1 E0 CE  P���
PAGE 23: 52 E7 4F 76  R�Ov
PAGE 24: 00 00 00 00  ....
PAGE 25: 00 00 00 00  ....
PAGE 26: 00 00 00 00  ....
PAGE 27: 00 00 00 00  ....
PAGE 28: 00 00 00 00  ....
PAGE 29: 00 00 00 00  ....
PAGE 30: 00 00 00 00  ....
PAGE 31: 00 00 00 00  ....
PAGE 32: 00 00 00 00  ....
PAGE 33: 00 00 00 00  ....
PAGE 34: 00 00 00 00  ....
PAGE 35: 00 00 00 00  ....
PAGE 36: 00 00 00 00  ....
PAGE 37: 00 00 00 00  ....
PAGE 38: 00 00 00 00  ....
PAGE 39: 00 00 00 00  ....
PAGE 40: 00 00 00 BD  ...�
PAGE 41: 07 00 00 08  ....