code hacking, zen coding

Atast CTF – Gadget – IDA static analysis PIC16F Blinker Write-Up

Gadget was an electronic challenge at the Atast CTF. You get a schematic design for ISIS and .hex file for the PIC16F CPU. I choose to use the evaluation version of PIC Simulator just to visualize what this design was about:


When you run the program, the 8 LEDs will blink at the same time in short and long patterns: could be morse ?

I don’t much about PIC and even less about electronic so let see how we can solve this challenge using only static analysis with IDA.

IDA will load the .hex file just fine. Make sure you uncheck “Memory layout” in the import options.

After reversing and renaming everything, its quite easy to understand what’s going on:

The program entry point:

CODE:0000 ; Reset Vector
CODE:0000 ; Attributes: thunk
CODE:0000                 ; public start
CODE:0000 start:
CODE:0000                 b       main
CODE:0000 ; End of function start

The leds are turned on by setting RB0->RB7 pins (PORTB) to 0xFF:

CODE:000A led_on:                                 ; CODE XREF: main:sequence_startp
CODE:000A                                         ; main+16p ...
CODE:000A                 movlw   0FF
CODE:000B                 bcf     BANK0:STATUS, RP0
CODE:000C                 bcf     BANK0:STATUS, RP1
CODE:000D                 movwf   BANK0:PORTB
CODE:000E                 return
CODE:000E ; End of function led_on

..and turned off by clearing PORTB (output value 0x0):

CODE:001E led_off:                                ; CODE XREF: main+14p
CODE:001E                                         ; main+18p ...
CODE:001E                 bcf     BANK0:STATUS, RP0
CODE:001F                 bcf     BANK0:STATUS, RP1
CODE:0020                 clrf    BANK0:PORTB
CODE:0021                 return
CODE:0021 ; End of function led_off

We need to wait some time between signals so we have delay loops like this one:

DATA:007B wait1           equ 7B                  ; DATA XREF: wait_for_dash+3w
DATA:007C wait2           equ 7C                  ; DATA XREF: wait_for_dash+5w
DATA:007D wait3           equ 7D                  ; DATA XREF: wait_for_dash+7w

CODE:0022 delay:                                  ; CODE XREF: main+15p
CODE:0022                                         ; main+1Dp ...
CODE:0022                 movlw   82 ; 'é'
CODE:0023                 bcf     BANK0:STATUS, RP0
CODE:0024                 bcf     BANK0:STATUS, RP1
CODE:0025                 movwf   wait2
CODE:0026                 movlw   0DD ; '¦'
CODE:0027                 movwf   wait3
CODE:0028 wait_loop:                              ; CODE XREF: delay+7j
CODE:0028                                         ; delay+9j
CODE:0028                 decfsz  wait3, f
CODE:0029                  b       wait_loop
CODE:002A                 decfsz  wait2, f
CODE:002B                  b       wait_loop
CODE:002C                 nop
CODE:002D                 nop
CODE:002E                 return
CODE:002E ; End of function delay

We set 2 or 3 byte registers (depend how long the pause needs to be) to some value and then we have loops that decrement them until zero like this:

for wait1 in range(0x15):
  for wait2 in range(0x82):
    for wait3 in range(0xDD):
      # do nothing

We can sort the delay functions using these 3-bytes counter values and assign them proper name:
– 0082DD: delay is used when in between led blink sequence, not useful for morse decoding
– 0082DD: short is a short delay used for blinking a led: dot
– 028699: middle is used for a long blink: dash
– 048E12: long is used for delay between blinks: space

There is different subs for each different pause: short, long, etc… Careful renaming will make the main function easy to understand:

CODE:0058 main:                                   ; CODE XREF: startj
CODE:0058                 bsf     BANK0:STATUS, RP0
CODE:0059 ; assume bank = 1
CODE:0059                 bcf     BANK1:STATUS, RP1
CODE:005A                 clrf    BANK1:TRISB
CODE:005B                 bcf     BANK1:STATUS, RP0
CODE:005C ; assume bank = 0
CODE:005C                 clrf    BANK0:PORTB
CODE:005D                 movlw   15
CODE:005E                 movwf   wait1
CODE:005F                 movlw   4B ; 'K'
CODE:0060                 movwf   wait2
CODE:0061                 movlw   0BE ; '¥'
CODE:0062                 movwf   wait3
CODE:0063 loop_wait1:                             ; CODE XREF: main+Cj main+Ej ...
CODE:0063                 decfsz  wait3, f
CODE:0064                  b       loop_wait1
CODE:0065                 decfsz  wait2, f
CODE:0066                  b       loop_wait1
CODE:0067                 decfsz  wait1, f
CODE:0068                  b       loop_wait1
CODE:0069                 nop
CODE:006A sequence_start:                         ; CODE XREF: main+72j
CODE:006A                 call    led_on
CODE:006B                 call    wait_for_dash
CODE:006C                 call    led_off
CODE:006D                 call    delay
CODE:006E                 call    led_on
CODE:006F                 call    wait_for_dash
CODE:0070                 call    led_off
CODE:0071                 call    wait_for_space
CODE:0072                 call    led_on
CODE:0073                 call    wait_for_dash
CODE:0074                 call    led_off
CODE:0075                 call    delay
CODE:0076                 call    led_on
CODE:0077                 call    wait_for_dot
CODE:0078                 call    led_off
CODE:0079                 call    delay
CODE:007A                 call    led_on
CODE:007B                 call    wait_for_dash
CODE:007C                 call    led_off
CODE:007D                 call    delay
CODE:007E                 call    led_on
CODE:007F                 call    wait_for_dot
CODE:0080                 call    led_off
CODE:0081                 call    wait_for_space
CODE:0082                 call    led_on
CODE:0083                 call    wait_for_dot
CODE:0084                 call    led_off
CODE:0085                 call    delay
CODE:0086                 call    led_on
CODE:0087                 call    wait_for_dot
CODE:0088                 call    led_off
CODE:0089                 call    delay
CODE:008A                 call    led_on
CODE:008B                 call    wait_for_dash
CODE:008C                 call    led_off
CODE:008D                 call    wait_for_space
CODE:008E                 call    led_on
CODE:008F                 call    wait_for_dash
CODE:0090                 call    led_off
CODE:0091                 call    delay
CODE:0092                 call    led_on
CODE:0093                 call    wait_for_dash
CODE:0094                 call    led_off
CODE:0095                 call    wait_for_space
CODE:0096                 call    led_on
CODE:0097                 call    wait_for_dash
CODE:0098                 call    led_off
CODE:0099                 call    delay
CODE:009A                 call    led_on
CODE:009B                 call    wait_for_dash
CODE:009C                 call    led_off
CODE:009D                 call    delay
CODE:009E                 call    led_on
CODE:009F                 call    wait_for_dash
CODE:00A0                 call    led_off
CODE:00A1                 call    wait_for_space
CODE:00A2                 call    led_on
CODE:00A3                 call    wait_for_dot
CODE:00A4                 call    led_off
CODE:00A5                 call    delay
CODE:00A6                 call    led_on
CODE:00A7                 call    wait_for_dash
CODE:00A8                 call    led_off
CODE:00A9                 call    delay
CODE:00AA                 call    led_on
CODE:00AB                 call    wait_for_dot
CODE:00AC                 call    led_off
CODE:00AD                 call    wait_for_space
CODE:00AE                 call    led_on
CODE:00AF                 call    wait_for_dot
CODE:00B0                 call    led_off
CODE:00B1                 call    delay
CODE:00B2                 call    led_on
CODE:00B3                 call    wait_for_dot
CODE:00B4                 call    led_off
CODE:00B5                 call    delay
CODE:00B6                 call    led_on
CODE:00B7                 call    wait_for_dot
CODE:00B8                 call    led_off
CODE:00B9                 call    wait_for_space
CODE:00BA                 call    led_on
CODE:00BB                 call    wait_for_dot
CODE:00BC                 call    led_off
CODE:00BD                 movlw   15
CODE:00BE                 movwf   wait1
CODE:00BF                 movlw   4B ; 'K'
CODE:00C0                 movwf   wait2
CODE:00C1                 movlw   0BE ; '¥'
CODE:00C2                 movwf   wait3
CODE:00C3 wait_loop2:                             ; CODE XREF: main+6Cj
CODE:00C3                                         ; main+6Ej ...
CODE:00C3                 decfsz  wait3, f
CODE:00C4                  b       wait_loop2
CODE:00C5                 decfsz  wait2, f
CODE:00C6                  b       wait_loop2
CODE:00C7                 decfsz  wait1, f
CODE:00C8                  b       wait_loop2
CODE:00C9                 nop
CODE:00CA                 b       sequence_start
CODE:00CA ; End of function main

Translating to morse code the different waits: — -.-. ..- — — .-. … .


… and another victory for IDA static analysis.

Download challenge file:
Full .HEX disassembly: blinker.asm