<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/sodnpoo.xsl"?>
<xml>
<post>
  <tag value="reverse engineering"/>
  <tag value="tiger"/>
  <tag value="wheel of fortune"/>
  <title>totp two factor auth on tiger's wheel of fortune</title>
  <date>
  24 Oct 2015
  </date>
  <p>
  </p>
  <image src="/posts.assets/wheel_of_fortune1.jpg"/>
  <p>
During our recent move we found an old Tiger "Wheel of Fortune" electronic game - most of my tools/toys were packed and/or moved at this point so I couldn't do much more than have a quick look inside. Last weekend I found myself wide-awake, very, very early and decided to take a closer look.
  </p>
  <image src="/posts.assets/wheel_of_fortune2.jpg"/>
  <p>
The game picks a category (phrase, person, thing etc) and an answer, then you and the cpu-controlled player two, take turns to spin the wheel and guess at the answer. There's a small number of categories built in, but more on the supplied cartridge ("Cartridge 1"). More cartridges were also available separately.
  </p>
  <p>
Probing the cart pins with my scope while pressing buttons, I could see that one line lit up when pressing the 'puzzle/cat./enter' button. More probing with my logic sniffer and bus pirate revealed it used a mode 1 SPI bus, with the LSB first. The read protocol is simple: a two byte address is sent by the game (via the MOSI line), and a one byte response is returned using MISO. For example here is the game (MOSI, third row) requesting the byte at 0x0 (two bytes: 0x0 and 0x0) and the cart returning 0xA5 (MISO, first row).
  </p>
  <image src="/posts.assets/wheel_of_fortune3.png"/>
  <p>
With the protocol worked out I wrote a python script to drive the bus pirate so I could sequentially read the cart's address space and dump the ROM. For dynamic analysis I also placed the dump in the progmem of an arduino mega, running a simple SPI loop that also logs all reads.
  </p>
  <pre>
00000000  a5 01 12 3a 21 f7 1a e4  23 17 22 e9 12 39 1c 1e  |...:!...#."..9..|
00000010  16 03 01 40 06 fc 1b 25  25 25 25 25 25 25 25 25  |...@...%%%%%%%%%|
00000020  25 25 25 25 25 25 25 25  25 25 25 25 25 00 00 00  |%%%%%%%%%%%%%...|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
  </pre>
  <p>
And after running numerous tests, seems to be explained as:
  </p>
  <pre>
0x00   0xA5 - magic byte, cart is ignored if this isn't here
0x01   0x01 - this seems to be the cart number; it's purpose is to detect if the
              cart has been changed and if so re-read 0x02(number of categories)
0x02   0x12 - number of categories (actually (n*2)-2))
0x03   0x3a - low byte of the address of the first category ('TITLE')
0x04   0x21 - high byte of the address of the first category
0x05   0xf7 - low byte of cat. 'PEOPLE'
0x06   0x1a - high byte of cat. 'PEOPLE'
0x07   0xe4 - low byte of cat. 'FICTIONAL CHARACTER'
0x08   0x23 - high byte of cat. 'FICTIONAL CHARACTER'
etc
  </pre>
  <p>
The game cycles though each category in turn until it runs out, it then reads 0x101 and 0x102, which eventually causes it to jump back to the first entry again.
  </p>
  <p>
Both the categories and the answers are stored as 20 byte long arrays, that are copied to the 2x 10 char display. Initially it looked as if the chars might just be ascii, but only the vowels were decoding correctly, the other letters appeared to be missing a bit. Turns out that the vowels are 'special' and have to be bought when playing the game - the missing bit is the 'buy' flag. Interesting there's a second flag - that's not used in the game - that gives you that letter, for free, from the start:
  </p>
  <pre>
    | |||| &lt;&lt;&lt; 0 - 31 (1=A, 2=B etc)
 0001 0011
 ^^^ &lt;&lt;&lt; flags
 ABC

 A = always show
 B = buy
 C = ?
  </pre>
  <p>
There's only 32 valid characters (A-Z and a handful of symbols) and possibly a third flag ('C') - although this didn't seem to have any effect during testing.
  </p>
  <p>
The game picks an answer by taking the base address of the category and multiplying an internal counter by 20.
  </p>
  <p>
Having worked all of that out I wouldn't to be able to do something at least a little bit useful; as I could 1) detect a button press and 2) display text on the screen I thought <a href="https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm">a TOTP token</a> might be interesting.
  </p>
  <p>
Because the game doesn't support numbers when reading from the cart - and a TOTP token is all numbers - I've had to come up with a 'creative' mapping (squint - it's almost right!):
  </p>
  <pre>
0 -> O
1 -> I
2 -> Z
3 -> E
4 -> A
5 -> S
6 -> G
7 -> T
8 -> B
9 -> P
  </pre>
  <p>
Here's a video showing it in action; the 'PRESS CAT FOR TOTP' message is the only answer in the embedded data, and all letters have the 'always show' bit set. The TOTP code is constantly calculated and written to a overlay variable that is read instead of the real address of the category when the button is pressed.
  </p>
  <p>
  <center><iframe width="560" height="315" src="//www.youtube.com/embed/p0db3RFKXow" frameborder="0"></iframe></center>
  </p>
  <p>
In a final design, the code would be installed on a ATTiny(+RTC) and placed inside a 3D printed cartridge shell, so it could quickly be swapped in when needed. An attacker looking to acquire the token would have an additional barrier of identifying the device amongst more obvious targets.
  </p>
  <p>
Code is hacked together from many SPI examples and <a href="http://www.lucadentella.it">Luca Dentella's TOTP code</a>. It can be found <a href="/posts.assets/wheel_of_fortune1.ino">here</a>.
  </p>
  <p>
  </p>
</post>
</xml>
