Hardcoded password




We are given the DVID card and asked to enter the right password over a serial communication. We also have a USB UART to establish the serial communication. And finally we have a USB ASP to flash the firmware and extract it.

Serial communication

What is it ?

Since I have approximately zero knowledge of electronics, I am asking myself right now, what exactly defines a serial communication ?

After reading an introduction from contec.com I learnt that serial communication is a communication method that uses one or two transmission lines to send and receive data, and that data is continuously sent and received one bit at a time.

There are multiple serial communication standards which are either simplex, multiplex, full-duplex, half-duplex, single-ended, differential…


The most widely used standard is RS-232C. The description of each PIN of this standard can be found below. I also marked the pins available on the board and the given USB that should be used to establish the serial communication.

Pin No. Signal name Full name We have it
1 DCD Data Carrier Detect No
2 RxD Received Data Yes
3 TxD Transmitted Data Yes
4 DTR Data Terminal Ready Yes
5 SG Signal Ground No
6 DSR Data Set Ready No
7 RTS Request To Send No
8 CTS Clear To Send On usb only
9 RI Ring Indicator No
CASE FG Frame Ground No


Now we have an idea of what the pins are used for but we are still lacking the understanding of the protocol.

A good introduction is a tutorial available on sparkfun.com

There we learn that embedded systems usually communicate at a transistor-transistor logic level (TTL) which is slightly different from RS-232C. As it turns out, our USB UART is sold as a “USB To TTL Module”.

We also learn that microcontrollers use UART (universal asynchronous receiver/transmitter) to convert their data on a parallel bus to and from a serial interface. Below is a simplified UART interface : the parallel on one end and the serial on the other.

                     |            |           |
         +-----------+D0          |           |
         |  +--------|D1          |           |
         |  |  +-----|D2          |         RX+<------+
Data Bus |  |  |  +--+D3          |           |
  +---------------+  |            |         TX+------->
         |  |  |  +--+D4          |           |
         |  |  +-----|D5          |           |
         |  +--------|D6          |           |
         +-----------+D7          |           |
                     |            |           |
                     |            |           |
   Control I/O  +----+R/W         |           |
  +------------------|CLK         |           |
                +----+INT         |           |
                     |            |           |
                     |            |           |
                     |            |           |
                     |            |           |
                     |  Parallel  |   Serial  |
                     |            |           |

Erwan Dano

ATmega328p and UART

We know that our board uses an ATmega328p, and we can see that the board has a component labelled UART.

If we take a look at the ATmega328p pin mapping here is what we get (limited to the interesting parts):

       |   `--´   |
       |          |
       |          |
RESET  |1       28|
  RXD  |2       27|
  TXD  |3       26|
 INT0  |4       25|
 INT1  |5       24|
   T0  |6       23|
  VCC  |7       22| GND
  GND  |8       21|
       |9       20|
       |10      19|
       |11      18|
       |12      17|
       |13      16|
       |14      15|
       |          |
       |          |

Now if we look at the board and the circuits on it we can draw the following connections :

       UART                     +----------+
                                |   `--´   |
+----------+                    |          |
|          |                    |          |
|          |                    |1       28|
|       RX +--------------------+2       27|
|       TX +--------------------+3       26|
|          |                    |4       25|
|          |                    |5       24|
|          |                    |6       23|
|          |                    |7       22|
|          |                    |8       21|
|          |                    |9       20|
|          |                    |10      19|
|          |                    |11      18|
|          |                    |12      17|
|          |                    |13      16|
+----------+                    |14      15|
                                |          |
                                |          |

I could not clearly see the GND and VCC connections with the ATmega328p already soldered on, but I have to assume that the UART’s VCC and GND are connected to the ATmega328p VCC and GND respectively.

Now we know that our ATmega328p already includes a UART and the board gives us an easy access.


Looking up for “what is VCC” we understand that VCC stands for Voltage Common Collector.

VCC is the power supply pin. GND is the ground.

We know have enough knowledge to connect the given USB to the board and not blow anything up.

Board connection

Once we have connected the board to our computer, the screen lights up and a message appears : A useful information is hardcoded, Find it to unlock.

Since we have connected the board to our computer through a serial port, we should be able to send it data; however we won’t be able to receive data from it as the board has not been configured to send data.

A quick DDG search for linux communicate over serial port gives us a tutorial explaining how we can do this.

Finding the board name

We connect the USB UART to our computer and use dmesg to get some info about what we just connected :

[166627.924066] usb 1-8: new full-speed USB device number 23 using xhci_hcd
[166628.073498] usb 1-8: New USB device found, idVendor=1a86, idProduct=7523
[166628.073505] usb 1-8: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[166628.073509] usb 1-8: Product: USB2.0-Serial
[166628.074457] ch341 1-8:1.0: ch341-uart converter detected
[166628.075089] usb 1-8: ch341-uart converter now attached to ttyUSB0

In the tutorial we found we are told to use dmesg | egrep 'serial|ttyS to retrieve the information about our just connected serial port; however this won’t work in our case since the USB device is clearly attached to ttyUSB0 as mentionned in the logs.

cu command

The cu command acts as a dial in terminal. Once installed, we add ourselves to the dialout group in order to use the command without sudo.

sudo usermod -aG dialout braincoke

There is a complete guide explaining serial communication and the tools written by David S.Lawyer. And a tutorial about cu can be found here.

To initiate a serial communication we use the command cu -l /dev/ttyUSB0 -s <baud_rate>.

We don’t have the baud rate so we have to try multiple one until we find the right one. However the most used baud rate in microcontroller is 9600. When we use 9600 and we type in some random password, the board reacts and the screen display indicates that we have the wrong password.

cu -l /dev/ttyUSB0 -s 9600

To close a connection we use : ~. To list all commands ~?.


We can also use screen to connect to the board :

screen /dev/ttyS0 9600

To see the processes using /dev/ttyUSB0 we use:

sudo lsof /dev/ttyUSB0

This can come in handy when we get a message like [screen is terminating]. In this case we can kill the processes listed by lsof to solve the problem.

To kill a screen in the session :CTRL + A, k To get info in a screen session :CTRL + A, i

Extracting the firmware

The board told us that the password is hardcoded, so we should be able to find it in the firmware.

After some research, we find a post explaining how to update a firmware with a USBAsp.

Even though this was not exactly what we were looking for, we learn about the existence of the command avrdude.

After searching for “avrdude extract firmware” we learn that it is possible to extract firmware with avrdude.

The example given is the following :

avrdude -patmega328p -carduino -P/dev/cu.usbmodemFD121 -b115200 -U flash:r:"flash.bin":r 

Where :

  • -p specifies the MCU connected to the programmer. We can show a list of
    valid part numbers with -C "?". Our part number is m328p since the ATmega is a 328p.
  • -c specifies the programmer-id. We can show a list of valid programmer-id with -c "?".
  • -P specifies the port to identify the device.
  • -b is the baud rate 9600 in our case.
  • -U describes the memory operation to do -U memtype:op:filename:format:
    • memtype : we target the flash ROM of the device.
    • op : we wish to read the flash ROM, so we will use r.
    • format : we will have to use r for raw binary.

Since we use a USBAsp to get the firmware we will have to use the programmer-id usbasp.

Now we have to find the port to use. When searching for more information in the avrdude man page we find the following mention of USBAsp :

The avrftdi, USBasp ISP and USBtinyISP adapters are also supported, provided avrdude has been compiled with libusb support.
USBasp ISP and USBtinyISP both feature simple firmware-only USB implementations, running on an ATmega8 (or ATmega88), or ATtiny2313, respectively.

This documentation was way too cryptic for me to understand right away, so after researching some example usage of USBAsp and avrdude on the net I found out that you don’t need to specify a port when using -c usbasp.

In the end our final command is :

avrdude -pm328p -cusbasp -b9600 -U flash:r:"flash.bin":r

We get the following output from the command

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading flash memory:

Reading | ################################################## | 100% 16.63s

avrdude: writing output file "flash.bin"

avrdude: safemode: Fuses OK (E:FD, H:DA, L:FF)

avrdude done.  Thank you.

You’re welcome avrdude.

Finding the hardcoded password

We just run strings flash.bin to list hardcoded strings in the binary :

T01 Hard.Pass.   
A useful information is hardcoded, Find it to unlock
Wrong password
Try again
Pass : 
Well done ! Challenge unlocked

Well 1234 certainly looks like a robust password, if we try it on the board we will see that we just solved the challenge !


If we have a sadomasochism fetish, we can use radare2 to examine the extracted binary.

We will have to specify the architecture to radare with the -a option :

r2 -a avr flash.bin
 -- Control the height of the terminal on serial consoles with e scr.height

We start an analysis with aaa:

[0x00000a8e]> aaa
[Cannot find function 'entry0' at 0x00000a8e entry0 (aa)
[x] Analyze all flags starting with sym. and entry0 (aa)
[ ] 
[Value from 0x00000000 to 0x00008000
aav: 0x00000000-0x00008000 in 0x0-0x8000
[SPM: I dont know what to do with SPMCSR 783318e0.
SPM: I dont know what to do with SPMCSR 783318e0.
SPM: I dont know what to do with SPMCSR 783318e0.
SPM: I dont know what to do with SPMCSR 783318e0.
SPM: I dont know what to do with SPMCSR 783318e0.
[x] Analyze function calls (aac)
[SPM: I dont know what to do with SPMCSR 783318b0.es (aar)
SPM: I dont know what to do with SPMCSR 783318b0.
SPM: I dont know what to do with SPMCSR 783318b0.
SPM: I dont know what to do with SPMCSR 783318b0.
SPM: I dont know what to do with SPMCSR 783318b0.
[x] Analyze len bytes of instructions for references (aar)
[x] Use -AA or aaaa to perform additional experimental analysis.
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)

As we can see radare has some trouble analysing the binary.

Anyway, we start looking for the string “Wrong” to see where it is placed in the binary and have a better understanding of its structure.

[0x00000a8e]> / Wrong
Searching 5 bytes in [0x0-0x8000]
hits: 1
0x00003e02 hit0_0 .t to unlock 50Wrong passwordTry ag.

The string “Wrong” is found at 0x3e02. Let’s have a look at the data around this place. The following command displays 400 words starting at 0x3e02-200

[0x00000a8e]> pxw 400 @ 0x3e02-200
0x00003d3a  0xe0d5e4c6 0x01fec004 0x1c8a940e 0x34c79621  ............!..4
0x00003d4a  0xf7c907d1 0xcfff94f8 0xb0000001 0x00008003  ................
0x00003d5a  0x05000000 0x9c057206 0xcd065205 0xbf05ab05  .....r...R......
0x00003d6a  0x00000005 0x320a5f00 0xf10a8e0a 0x160a2a08  ....._.2.....*..
0x00003d7a  0x000a070a 0x47000000 0x8e05720b 0x7e05710a  .......G.r...q.~
0x00003d8a  0x1a08f106 0x0e08f209 0x21090209 0x3c08f109  ...........!...<
0x00003d9a  0xb80d7507 0x3a0afc0a 0xb0081d08 0x0d075107  .u.....:.....Q..
0x00003daa  0x3231000a 0x54003433 0x48203130 0x2e647261  ..1234.T01 Hard.
0x00003dba  0x73736150 0x2020202e 0x20002500 0x41003020  Pass.   .%.  0.A
0x00003dca  0x65737520 0x206c7566 0x6f666e69 0x74616d72   useful informat
0x00003dda  0x206e6f69 0x68207369 0x63647261 0x6465646f  ion is hardcoded
0x00003dea  0x6946202c 0x6920646e 0x6f742074 0x6c6e7520  , Find it to unl
0x00003dfa  0x006b636f 0x00303520 0x6e6f7257 0x61702067  ock. 50.Wrong pa
0x00003e0a  0x6f777373 0x540a6472 0x61207972 0x6e696167  ssword.Try again
0x00003e1a  0x73615000 0x203a2073 0x30303100 0x6c655700  .Pass : .100.Wel
0x00003e2a  0x6f64206c 0x2120656e 0x61684320 0x6e656c6c  l done ! Challen
0x00003e3a  0x75206567 0x636f6c6e 0x0064656b 0xffffffff  ge unlocked.....
0x00003e4a  0xffffffff 0xffffffff 0xffffffff 0xffffffff  ................
0x00003e5a  0xffffffff 0xffffffff 0xffffffff 0xffffffff  ................
0x00003e6a  0xffffffff 0xffffffff 0xffffffff 0xffffffff  ................
0x00003e7a  0xffffffff 0xffffffff 0xffffffff 0xffffffff  ................
0x00003e8a  0xffffffff 0xffffffff 0xffffffff 0xffffffff  ................
0x00003e9a  0xffffffff 0xffffffff 0xffffffff 0xffffffff  ................
0x00003eaa  0xffffffff 0xffffffff 0xffffffff 0xffffffff  ................
0x00003eba  0xffffffff 0xffffffff 0xffffffff 0xffffffff  ................

Note that we can display the result of our subtraction with ? <math expression>. Here we see that all the strings are bundled together. We find our password 1234 once again, but I’ll turn a blind eye on it for now.

Let’s try to find where the string “Wrong password” is called. We know that the string is located at 0x3e02 :

[0x00003d3a]> ps @ 0x3e02
Wrong password
Try again
http://2015.zeronights.org/assets/files/43-bolshev-ryutin.pdf https://www.youtube.com/watch?v=zk3JdMOQPc8 https://github.com/radare/radare2/blob/master/doc/avr.md https://engineering.eckovation.com/arduino-architecture-explained/ https://stackoverflow.com/questions/5141177/atmel-avr-disassembler https://code.woboq.org/gcc/gcc/config/avr/avr-mcus.def.html Datasheet https://www.sparkfun.com/datasheets/Components/SMD/ATMega328.pdf sudo apt-get install gcc-avr avr-objdump -d -m avr:5 flash.bin Correct baud rate is 115200