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 ; Attributes: thunk
CODE:0000
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 ; 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 ; 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: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
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 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 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
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
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
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: — -.-. ..- — — .-. … .
Flag: MCUMORSE
… and another victory for IDA static analysis.
Download challenge file: chall9.zip
Full .HEX disassembly: blinker.asm