Sunday, August 17, 2014

DEFCON 22 Impressions

For the third year in a row I was able to attend DEFCON (self funded), and I must say I'm completely hooked.

The crowds were even more out of control than last year.  I got in line for the badge around 6:30 Thursday morning, and the line was already humongous.  By the time they started handing out badges (9:00), the line extended all the way back to the casino and they had started turning folks away.  Amazing!

In fact, they ran out of badges by the end of the day.  Those folks who missed out on "The" badge, got a paper badge and a DEFCON 20 badge as a consolation prize.  I feel bad for the folks who didn't get a badge.  There were 14,000 badges and it wasn't enough.  I can imagine it's very hard to predict how many folks will attend a conference like DEFCON (especially since there's no pre-registration).  Still they usually get it right, I wonder what led to them to so completely misjudge how many badges they needed this  time.

Speaking of the badge, it was awesome!  Almost as good as the DEFCON 20 badge, and clearly a prize worth the wait.  As with the DEFCON 20 badge, it was based on the Parallax Propeller development system. http://www.parallax.com/news/2014-08-06/propeller-1-defcon-22-badges-las-vegas

I spent some time playing with the badge, mostly establishing communication between it and my Linux system (minicom, 57600 baud with ttyUSB0).  Once I got that running, the badge started typing random commands to the screen, but due to the primitive communications the commands were overwriting each other and I wasn't sure I was getting it all.  I then found the source for the badge on the CD they handed out.  :-)

Poking at the source I found the strings that the badge prints to the screen.  They were encoded, but the routines to decode them were in the source, so I wrote a quick and dirty program to print them all.  Below is a cleaned up version of that program, which decodes and prints all the "secret" hints that the badge types when you connect to it.  (Of course, this is just for the "Human" badge, I don't know what the other badges do.) I included the relevant code from the badge as comments in my program.




#!/usr/bin/env ruby

# Decode the "secret" strings in the defcon 22 badge source code.

################################################################
# Here's snippits of the spin source (and the strings) fromm the badge
#
#  RayNelson   byte      "IAIHG TPJNU QU CZR GALWXK DC MHR LANK FOTLA OTN LOYOC HPMPB PX HKICW",0
#  Test4       byte      "DID YOU REALLY THINK THAT IT WOULD BE SO EASY? Really?  Just running strings?",0
#  Greets      byte      16,77,85,66,83,69,67,85,32,74,69,32,84,85,86,83,69,68,32,74,77,85,68,74,79,32,74,77,69,13,0
#  Detective   byte      13,74,85,82,69,82,32,71,66,32,79,82,84,86,65,32,86,32,88,65,66,74,32,83,86,65,81,32,85,78,69,66,89,81,13,0
#  Scientist   byte      76,81,84,89,86,70,32,82,75,66,32,83,78,90,32,83,81,87,83,85,32,87,82,65,32,73,77,82,66,32,67,70,72,82,32,90,65,65,65,65,32,73,89,77,87,90,32,80,32,69,65,74,81,86,68,32,89,79,84,80,32,76,71,65,87,32,89,75,90,76,13,0
#  Diver       byte      10,"DBI DRO PSBCD RKVP YP RSC ZRYXO XEWLOB PYVVYGON LI RSC VKCD XKWO DROX DRO COMYXN RKVP YP RSC XEWLOB",CR,0
#  Driver      byte      "SOMETIMES WE HAVE ANSWERS AND DONT EVEN KNOW IT SO ENJOY THE VIEW JUST BE HAPPY",0
#  Politician  byte      83,83,80,87,76,77,32,84,72,67,65,80,32,81,80,32,74,84,32,73,87,69,32,87,68,88,70,90,32,89,85,90,88,32,85,77,86,72,88,72,32,90,65,32,67,66,32,80,65,69,32,88,82,79,76,32,70,65,89,32,73,80,89,75,13,0
#  Test3       byte      "ZGJG MTM LLPN C NTER MPMH TW",CR,0
#  Football    byte      "IT MIGHT BE HELPFUL LATER IF YOU KNOW HOW TO GET TO EDEN OR AT LEAST THE WAY",0
#  Mystery     byte      "OH A MYSTERY STRING I SHOULD HANG ON TO THIS FOR LATER I WONDER WHAT ITS FOR OR WHAT IT DECODES TO?",0
#
#  Cmd00       byte      $05, $42, $54, $57, $50, $20, $4A, $4E, $4C, $4D, $59, $20, $4D, $54
#              byte      $5A, $57, $58, $0D, $00, $4C, $4F, $56, $45, $00 
#  Cmd01       byte      $04, $41, $45, $58, $47, $4C, $20, $58, $5A, $0D, $00
#  Cmd02       byte      $0E, $47, $49, $50, $41, $57, $48, $0D, $00, $4C, $49, $46, $45, $00
#  Cmd03       byte      $0C, $45, $46, $4D, $4B, $20, $4D, $45, $58, $51, $51, $42, $0D, $00
#  Cmd04       byte      $04, $53, $46, $49, $43, $0D, $00, $47, $69, $47, $21, $00
#  Cmd05       byte      $14, $48, $49, $20, $43, $48, $58, $59, $4A, $59, $48, $58, $59, $48
#              byte      $4E, $20, $4E, $42, $49, $4F, $41, $42, $4E, $0D, $00
#  Cmd06       byte      $02, $50, $51, $20, $4B, $4F, $43, $49, $4B, $50, $43, $56, $4B, $51
#              byte      $50, $0D, $00, $4A, $6F, $6E, $6E, $79, $4D, $61, $63, $00
#  Cmd07       byte      $0C, $59, $4D, $44, $44, $4B, $20, $4D, $5A, $50, $20, $44, $51, $42
#              byte      $44, $41, $50, $47, $4F, $51, $0D, $00, $48, $41, $50, $50, $59, $00
#  Cmd08       byte      $05, $4A, $46, $59, $0D, $00, $48, $45, $41, $4C, $54, $48, $00
#  Cmd09       byte      $09, $4D, $58, $20, $57, $58, $43, $20, $5A, $44, $4E, $42, $43, $52
#              byte      $58, $57, $20, $4A, $44, $43, $51, $58, $41, $52, $43, $48, $0D, $00 
#  Cmd10       byte      $0F, $52, $44, $43, $48, $4A, $42, $54, $0D, $00
#  Cmd11       byte      $02, $45, $51, $50, $48, $51, $54, $4F, $0D, $00
#  Cmd12       byte      $19, $41, $54, $58, $0D, $00, $57, $45, $41, $4C, $54, $48, $00
#              byte      $31, $6F, $35, $37, $00
#
##################################
# Here's where the various hints are decoded.  Notice two different schemes are used.
#
#  term.caesar(@@Commands[idx])
#  term.caesar(@Greets)
#  term.otp(@Test3, @Test4)
#  term.caesar(@Detective)                                 ' display crypto string
#  term.otp(@Scientist, @Driver)
#  term.caesar(@Diver)
#  term.otp(@Politician, @Football)
#  term.otp(@RayNelson, @Mystery)
#
##################################
# Here are the actual spin decoding routines.  exor isn't actually used (here)
#
#pub caesar(p_zstr) | c                                          ' *1o57*   
#
#  lost := byte[p_zstr++]
#  repeat strsize(p_zstr)
#    c := byte[p_zstr++] 
#    case c
#      32    : tx(32)
#      13    : tx(13)
#      other : tx((((c-65)+26-lost)//26)+65)
#
#      
#pub exor(p_zstr)                                                ' *1o57*   
#
#  lost := byte[p_zstr++]
#  repeat strsize(p_zstr)
#    tx(byte[p_zstr++]^lost)
#    
#    
#pub otp(p_zstr1, p_zstr2)                                       ' *1o57*
#
#  repeat until (byte[p_zstr1] == 0)
#    if (byte[p_zstr1] == 32)
#      tx(32)
#      p_zstr1++
#      
#    elseif (byte[p_zstr1] == 13)
#      tx(13)
#      p_zstr1++
#      
#    elseif (byte[p_zstr2] == 32)
#      p_zstr2++
#      
#    else
#      tx((((byte[p_zstr1++]-65)+(byte[p_zstr2++]-65))//26)+65)
#
################################################################

#
# Here are my versions of the decoding routines
#

def caesar (message)
  decoded = ""
  lost = message.delete_at(0)

  message.each {|c|
    case c
    when 32 then result = 32
    when 13 then next
    when 0 then break
    else
      result = ((((c-65)+26-lost)%26)+65)
    end
    decoded = decoded + result.chr
  }
  decoded
end

def otp (message, key)
  decoded = ""

  msg_index = 0
  key_index = 0

  while msg_index < message.length
    if key_index < key.length
      c = message[msg_index]
      d = key[key_index]
      case c
      when 32 then 
        result = 32
        msg_index += 1
      when 13 then 
        msg_index += 1
        next
      when 0 then
        break
      else
        if d == 32 then
          key_index +=  1
          next
        else
          result = ((((c-65)+(d-65))%26)+65)
          msg_index += 1
          key_index += 1
        end
      end
      decoded = decoded + result.chr
    end
  end
  decoded
end

#
# A  couple of auxiliary routines to adjust data types.
#

def s2c (string)  # String2Char .. convert string of decimal numbers to array of chars
  result = []
  string.each_byte {|char|
    result.push(char)
  }
  result
end


def h2c  (array_string)   # Hex2Char .. convert string of Hex numbers (in spin format) to array of chars
  result = [];
  inter1 = ""
  inter1 = array_string.gsub(/\$/,'0x')
  inter1.scan(/0x../){|element| result.push(element.hex)}

  result
end

#
# OK, finally. Decode the all the hints and print them
#

cmd00 = h2c ("$05, $42, $54, $57, $50, $20, $4A, $4E, $4C, $4D, $59, $20, $4D, $54, $5A, $57, $58, $0D, $00, $4C, $4F, $56, $45, $00")
puts "caeser(Cmd00) = #{caesar(cmd00)}"

cmd01 = h2c ("$04, $41, $45, $58, $47, $4C, $20, $58, $5A, $0D, $00")
puts "caesar(Cmd01) = #{caesar(cmd01)}"

cmd02 = h2c("$0E, $47, $49, $50, $41, $57, $48, $0D, $00, $4C, $49, $46, $45, $00")
puts "caesar(Cmd02) = #{caesar(cmd02)}"

cmd03 = h2c("$0C, $45, $46, $4D, $4B, $20, $4D, $45, $58, $51, $51, $42, $0D, $00")
puts "caesar(Cmd03) = #{caesar(cmd03)}"

cmd04 = h2c("$04, $53, $46, $49, $43, $0D, $00, $47, $69, $47, $21, $00")
puts "caesar(Cmd04) = #{caesar(cmd04)}"

cmd05 = h2c("$14, $48, $49, $20, $43, $48, $58, $59, $4A, $59, $48, $58, $59, $48, $4E, $20, $4E, $42, $49, $4F, $41, $42, $4E, $0D, $00")
puts "caesar(Cmd05) = #{caesar(cmd05)}"

cmd06 = h2c("$02, $50, $51, $20, $4B, $4F, $43, $49, $4B, $50, $43, $56, $4B, $51, $50, $0D, $00, $4A, $6F, $6E, $6E, $79, $4D, $61, $63, $00")
puts "caesar(Cmd06) = #{caesar(cmd06)}"

cmd07 = h2c("$0C, $59, $4D, $44, $44, $4B, $20, $4D, $5A, $50, $20, $44, $51, $42, $44, $41, $50, $47, $4F, $51, $0D, $00, $48, $41, $50, $50, $59, $00")
puts "caesar(Cmd07) = #{caesar(cmd07)}"

cmd08 = h2c("$05, $4A, $46, $59, $0D, $00, $48, $45, $41, $4C, $54, $48, $00")
puts "caesar(Cmd08) = #{caesar(cmd08)}"

cmd09 = h2c("$09, $4D, $58, $20, $57, $58, $43, $20, $5A, $44, $4E, $42, $43, $52, $58, $57, $20, $4A, $44, $43, $51, $58, $41, $52, $43, $48, $0D, $00")
puts "caesar(Cmd09) = #{caesar(cmd09)}"

cmd10 = h2c("$0F, $52, $44, $43, $48, $4A, $42, $54, $0D, $00")
puts "caesar(Cmd10) = #{caesar(cmd10)}"

cmd11 = h2c("$02, $45, $51, $50, $48, $51, $54, $4F, $0D, $00")
puts "caesar(Cmd11) = #{caesar(cmd11)}"

cmd12 = h2c("$19, $41, $54, $58, $0D, $00, $57, $45, $41, $4C, $54, $48, $00, $31, $6F, $35, $37, $00")
puts "caesar(Cmd12) = #{caesar(cmd12)}"

greets = [16,77,85,66,83,69,67,85,32,74,69,32,84,85,86,83,69,68,32,74,77,85,68,74,79,32,74,77,69,13,0]
puts "caesar(Greets) -> #{caesar(greets)}\n"

test3 = s2c ("ZGJG MTM LLPN C NTER MPMH TW")
test4 = s2c("DID YOU REALLY THINK THAT IT WOULD BE SO EASY? Really?  Just running strings?")
puts "otp (Test3, Test4) -> #{otp(test3, test4)}"

detective = [13,74,85,82,69,82,32,71,66,32,79,82,84,86,65,32,86,32,88,65,66,74,32,83,86,65,81,32,85,78,69,66,89,81,13,0]
puts "caesar(Detective) -> #{caesar(detective)}\n"

scientist = [76,81,84,89,86,70,32,82,75,66,32,83,78,90,32,83,81,87,83,85,32,87,82,65,32,73,77,82,66,32,67,70,72,82,32,90,65,65,65,65,32,73,89,77,87,90,32,80,32,69,65,74,81,86,68,32,89,79,84,80,32,76,71,65,87,32,89,75,90,76,13,0]
driver = s2c ("SOMETIMES WE HAVE ANSWERS AND DONT EVEN KNOW IT SO ENJOY THE VIEW JUST BE HAPPY")
puts "otp (Scientist, Driver) ->  #{otp(scientist, driver)}"

diver = [10] + s2c("DBI DRO PSBCD RKVP YP RSC ZRYXO XEWLOB PYVVYGON LI RSC VKCD XKWO DROX DRO COMYXN RKVP YP RSC XEWLOB")
puts "caesar (Diver) -> #{caesar(diver)}"

politician = [83,83,80,87,76,77,32,84,72,67,65,80,32,81,80,32,74,84,32,73,87,69,32,87,68,88,70,90,32,89,85,90,88,32,85,77,86,72,88,72,32,90,65,32,67,66,32,80,65,69,32,88,82,79,76,32,70,65,89,32,73,80,89,75,13,0]
football = s2c("IT MIGHT BE HELPFUL LATER IF YOU KNOW HOW TO GET TO EDEN OR AT LEAST THE WAY")
puts "otp(Politician, Football) -> #{otp(politician, football)}"

raynelson = s2c("IAIHG TPJNU QU CZR GALWXK DC MHR LANK FOTLA OTN LOYOC HPMPB PX HKICW")
mystery = s2c("OH A MYSTERY STRING I SHOULD HANG ON TO THIS FOR LATER I WONDER WHAT ITS FOR OR WHAT IT DECODES TO?")
puts "otp(RayNelson, Mystery) -> #{otp(raynelson, mystery)}"


And here's the output from this program:

caeser(Cmd00) = WORK EIGHT HOURS
caesar(Cmd01) = WATCH TV
caesar(Cmd02) = SUBMIT
caesar(Cmd03) = STAY ASLEEP
caesar(Cmd04) = OBEY
caesar(Cmd05) = NO INDEPENDENT THOUGHT
caesar(Cmd06) = NO IMAGINATION
caesar(Cmd07) = MARRY AND REPRODUCE
caesar(Cmd08) = EAT
caesar(Cmd09) = DO NOT QUESTION AUTHORITY
caesar(Cmd10) = CONSUME
caesar(Cmd11) = CONFORM
caesar(Cmd12) = BUY
caesar(Greets) -> WELCOME TO DEFCON TWENTY TWO
otp (Test3, Test4) -> COME AND PLAY A GAME WITH ME
caesar(Detective) -> WHERE TO BEGIN I KNOW FIND HAROLD
otp (Scientist, Driver) ->  DEFCON DOT ORG SLASH ONE ZERO FIVE SEVEN SLASH I WONDER WHAT GOES HERE
caesar (Diver) -> TRY THE FIRST HALF OF HIS PHONE NUMBER FOLLOWED BY HIS LAST NAME THEN THE SECOND HALF OF HIS NUMBER
otp(Politician, Football) -> ALBERT MIGHT BE ON THE PHONE WITH HAROLD SO IF ITS BUSY TRY BACK
otp(RayNelson, Mystery) -> WHITE LINES IN THE MIDDLE OF THE ROAD THATS THE WORST PLACE TO DRIVE

Of course, this was  just scratching  the surface.  To actually solve the mystery of the badge was a massive and extremely challenging undertaking.  Here's one description of the entire solution: http://potatohatsecurity.tumblr.com/post/94565729529/defcon-22-badge-challenge-walkthrough

Many of the talks I was able to get into were excellent, with the most enjoyable one being the very last talk of  the conference, "Elevator Hacking" by Deviant Ollam and Howard Payne.  Wow, I'll never be able to look at elevator the same way again!  I recommend looking for it when the video becomes available.

At the closing ceremony, DT gave the best news we could have asked for ... next year's DEFCON will be hosted at both the Bally and Paris casino/conference centers.  This ought to resolve the space problems which have plagued DEFCON the last few years.

I'm already looking forward to it!