Reverse Engineering ESP8266 firmware

Does anybody know if its possible to decompile a flash dump of an ESP8266? I'm looking to read a program from a chip and try to figure out what it's doing. It sends an ESP-Now signal which appears to have 4 random bytes, but I'm pretty sure their not really random as when i try to duplicate it, the receiving device does not respond.

1 Like

Sounds like a rolling code encrypted signal, which would be difficult to crack.

Decompile ? no. Even if you know the core version (if it was created with the arduino-esp8266 core that is) i know of no de-compile. I don't think you can even do that on the simpler AVR's you know. Converting Assembler back to C++ is not a thing that can easily be done.

I don't necessarily mean back to c++. I'd settle for assembly and trying to make sense of it.

As far as the rolling code...perhaps. Most of what is sent is consistent and can be duplicated, it's just 4 bytes on the end that are always changing.

1 Like

You need the firmware in binary first. Does the ESP8266 board have a built-in SPI-FLASH you could desolder and read? You will likely have to desolder the metal can first. I hope you don't mind destroying a few of these devices in the reverse-engineering process.

I came across the following link, but I have not tried it yet.

this will readout the bytes and you will be only able to store exact these bytes into another ESP8266 and that's it.

You seem to have not yet understood what compiling means
compiling means translate the human-readable source-code into assembler-code

after compiling the code looks like this
image

pure numbers

now reverse engineering requires to know which number is the startpoint of the code.

If you don't know the startpoint of the code a lot of additional work with try and error must be done to only find the startpoint
If you don't know the startpoint you can't tell if a number is a assembler-command or assembler-data
and you will MIS-interpred the whole code

Afdter having found the startpoint you have to compare long sequences of numbers if they fit to whatever pre-compiled sequence of numbers that mean whatever c++function

And as all of these C++ can be parameterised in millions of ways you even have to estimate if it might be this byte-sequence or that.

This all requires a knowledge-level that goes beyond even the best ESP32-users here in the forum.

It will take you years to gain that amount of knowledge and expertise.
You will need very very special software to automate this work for you
comparing the bytesequencies
starting at byte 1
starting at byte 2
starting at byte 3
...
starting at byte 100.000
if the bytesequence matches one out of 100.000 bytesequences that mean xy

If the secret service of the USA would catch a chinese drone a team of 20 very high skilled specialists will try to do this process and will need months working on it to understand what the bytesequences inside the flash-memory do.

So IMHO forget it. You will be 10 times faster to develop your own brandnew system from scratch that does the same thing.
Even if you are a complete beginner about programming in C++

best regards Stefan

that's exactly how those 4 bytes are described in the protocol (it's documented here in the frame format)

The Random Value field is used to prevent relay attacks

Actually I do understand what decompile means, and I actually said, "is style for assembly."

Stop assuming you know everything and being negative. And, as far as I know, typically the user code starts at address 0x1000 while the bootloader is at 0x0.

I know exactly what most of the code does as far as controlling, inputs and outputs as well as 9 out of the 13 bytes it sends for each packet it sends. And, yeah, it might take me a while, maybe even longer than someone who thinks they know everything about it, but I think I have a reasonable starting point.

So, I see the random bytes in the frame format, but this is something being sent in the,"vendor specific content" section and after the 9 bytes that I am able to decode, not before. Could be the vendor's own version of that somehow though.

the frame struct looks like this

typedef struct {
    uint16_t frame_head;
    uint16_t duration;
    uint8_t destination_address[6];
    uint8_t source_address[6];
    uint8_t broadcast_address[6];
    uint16_t sequence_control;

    uint8_t category_code;
    uint8_t organization_identifier[3]; // 0x18fe34
    uint8_t random_values[4];
    struct {
        uint8_t element_id;                 // 0xdd
        uint8_t lenght;                     //
        uint8_t organization_identifier[3]; // 0x18fe34
        uint8_t type;                       // 4
        uint8_t version;
        uint8_t body[0];
    } vendor_specific_content;
} __attribute__((packed)) espnow_frame_format_t;

If I'm understanding it correctly, that would put the 4 random bytes before the data being sent, would it not?

Also, when I write my own program to send test data, I never see any random bytes in the data part.

yes, looking at that struct the 4 bytes for random_values are just before the vendor_specific_content

there might also be encryption at play for security?

Security

ESP-NOW uses the CCMP method, which is described in IEEE Std. 802.11-2012, to protect the vendor-specific action frame. The Wi-Fi device maintains a Primary Master Key (PMK) and several Local Master Keys (LMK). The lengths of both PMK and LMk are 16 bytes.

  • PMK is used to encrypt LMK with the AES-128 algorithm. Call esp_now_set_pmk() to set PMK. If PMK is not set, a default PMK will be used.
  • LMK of the paired device is used to encrypt the vendor-specific action frame with the CCMP method. The maximum number of different LMKs is six. If the LMK of the paired device is not set, the vendor-specific action frame will not be encrypted.

I had that thought too, but two things made me dismiss it.

The first 9 bytes are consistent, depending on which inputs are triggered. I don't know much about encryption, but I was thinking that if the last 4 bytes were random these might be as well.

Then three was this:

Encrypting multicast vendor-specific action frame is not supported.

And it definitely sends in multicast to all devices on the same channel, always channel 1. I've tried listening on other channels and get nothing.

Interesting enough, in arduino, as far as I know you can't specify two different channels for Wi-Fi STA mode and the ESP-Now. But the receiving device (with ESP32) connects to my access point on a different channel while listening for ESP-Now on channel 1. Not sure if this is a feature only available through ESP-IDF maybe?

If you can recognize data then clearly there is no crypto.

That's what I was thinking as well. There has to be some rhyme or reason to the last 4 bytes. Here's a capture of what is received in bit form.

Data: LEN- Byte 1 - Byte 2 - Byte 3 - Byte 4 - Byte 5 - Byte 6 - Byte 7 - Byte 8 - Byte 9 - Byte 10- Byte 11- Byte 12- Byte 13
       13-10000001-00101100-00111101-00000000-00000000-00100000-00000010-00000001-01010110-00010110-01111010-11010010-00000001
       13-10000001-00101100-00111101-00000000-00000000-00100000-00000010-00000001-01010110-00010110-01111010-11010010-00000001
       13-10000001-00101100-00111101-00000000-00000000-00100000-00000010-00000001-01010110-00010110-01111010-11010010-00000001
       13-10000001-00101100-00111101-00000000-00000000-00100000-00000010-00000001-01010110-00010110-01111010-11010010-00000001
       13-10000001-00101100-00111101-00000000-00000000-00100000-00000010-00000001-01010110-00010110-01111010-11010010-00000001
       13-10000001-00101100-00111101-00000000-00000000-00100000-00000010-00000001-01010110-00010110-01111010-11010010-00000001
       13-10000001-00101100-00111101-00000000-00000000-00100000-00000010-00000001-01010110-00010110-01111010-11010010-00000001
       13-10000001-00101101-00111101-00000000-00000000-00100000-00000010-00000001-01010100-10000011-01111101-01110010-01001111
       13-10000001-00101101-00111101-00000000-00000000-00100000-00000010-00000001-01010100-10000011-01111101-01110010-01001111
       13-10000001-00101101-00111101-00000000-00000000-00100000-00000010-00000001-01010100-10000011-01111101-01110010-01001111
       13-10000001-00101101-00111101-00000000-00000000-00100000-00000010-00000001-01010100-10000011-01111101-01110010-01001111
       13-10000001-00101101-00111101-00000000-00000000-00100000-00000010-00000001-01010100-10000011-01111101-01110010-01001111
       13-10000001-00101101-00111101-00000000-00000000-00100000-00000010-00000001-01010100-10000011-01111101-01110010-01001111
       13-10000001-00101101-00111101-00000000-00000000-00100000-00000010-00000001-01010100-10000011-01111101-01110010-01001111
       13-10000001-00101110-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010001-11100110-11100100-01100010
       13-10000001-00101110-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010001-11100110-11100100-01100010
       13-10000001-00101110-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010001-11100110-11100100-01100010
       13-10000001-00101110-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010001-11100110-11100100-01100010
       13-10000001-00101110-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010001-11100110-11100100-01100010
       13-10000001-00101110-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010001-11100110-11100100-01100010
       13-10000001-00101110-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010001-11100110-11100100-01100010
       13-10000001-00101111-00111101-00000000-00000000-00100000-00000010-00000001-01010110-11011101-11000100-00011101-00100100
       13-10000001-00101111-00111101-00000000-00000000-00100000-00000010-00000001-01010110-11011101-11000100-00011101-00100100
       13-10000001-00101111-00111101-00000000-00000000-00100000-00000010-00000001-01010110-11011101-11000100-00011101-00100100
       13-10000001-00101111-00111101-00000000-00000000-00100000-00000010-00000001-01010110-11011101-11000100-00011101-00100100
       13-10000001-00101111-00111101-00000000-00000000-00100000-00000010-00000001-01010110-11011101-11000100-00011101-00100100
       13-10000001-00101111-00111101-00000000-00000000-00100000-00000010-00000001-01010110-11011101-11000100-00011101-00100100
       13-10000001-00101111-00111101-00000000-00000000-00100000-00000010-00000001-01010110-11011101-11000100-00011101-00100100
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011
       13-10000001-00110000-00111101-00000000-00000000-00100000-00000010-00000001-01010100-00010010-10000001-00101111-10110011

As you can see, it sends the signal multiple times to make sure that the receiver got it.

Here's another capture of it with what I've decoded.

Pairing (1) - Sequence (2-5) - Unknown (6) - Button (7) - Unknown (8) - Unknown (9) - Unknown (10) - Unknown (11) - Unknown (12) - Unknown (13)
    129     -      15671     -     32      -     Off    -      1      -     84      -     130      -     163      -     51       -     213
    129     -      15672     -     32      -     Off    -      1      -     86      -     156      -     120      -     65       -     30
    129     -      15673     -     32      -     Off    -      1      -     84      -     52       -     165      -     255      -     153
    129     -      15674     -     32      -     Off    -      1      -     84      -      0       -     198      -     37       -     171
    129     -      15675     -     32      -     Off    -      1      -     84      -     230      -     96       -     56       -     226
    129     -      15676     -     32      -     Off    -      1      -     86      -     46       -     175      -     156      -     77
    129     -      15677     -     32      -     Off    -      1      -     84      -     196      -     238      -     106      -     145
    129     -      15678     -     32      -     Off    -      1      -     84      -     16       -     104      -     224      -     93
    129     -      15679     -     32      -     Off    -      1      -     84      -     101      -     172      -     225      -     146
    129     -      15680     -     32      -     Off    -      1      -     86      -     82       -      4       -     31       -     141
    129     -      15681     -     32      -     Off    -      1      -     84      -     178      -     38       -     101      -     214
    129     -      15682     -     32      -     Off    -      1      -     84      -     199      -      3       -     167      -     46
    129     -      15683     -     32      -     Off    -      1      -     84      -     209      -     31       -     131      -     118
    129     -      15684     -     32      -     Off    -      1      -     84      -     110      -     110      -     144      -     36
    129     -      15685     -     32      -     Off    -      1      -     84      -     131      -     252      -     42       -     127
    129     -      15686     -     32      -     Off    -      1      -     84      -     39       -     30       -     154      -     188
    129     -      15687     -     32      -     Off    -      1      -     84      -     80       -     170      -     187      -     181
    129     -      15688     -     32      -     Off    -      1      -     84      -     231      -     239      -     10       -     46
    129     -      15689     -     32      -     Off    -      1      -     84      -     220      -     172      -     192      -     246
    129     -      15690     -     32      -     Off    -      1      -     84      -     171      -     152      -     185      -     76
    129     -      15691     -     32      -     Off    -      1      -     84      -     64       -     224      -     122      -     22
    129     -      15692     -     32      -     Off    -      1      -     83      -     104      -     13       -     160      -     137
    129     -      15693     -     32      -     Off    -      1      -     84      -     127      -     109      -     136      -     44
    129     -      15694     -     32      -     Off    -      1      -     82      -     40       -     186      -     197      -     124
    129     -      15695     -     32      -     Off    -      1      -     87      -     74       -     213      -     144      -     176
    129     -      15696     -     32      -     Off    -      1      -     87      -     125      -     130      -     77       -     206
    129     -      15697     -     32      -     Off    -      1      -     83      -     81       -     135      -     184      -     205
    129     -      15698     -     32      -     Off    -      1      -     83      -     209      -     72       -     152      -     28
    129     -      15699     -     32      -     Off    -      1      -     82      -     144      -     88       -      2       -     214
    129     -      15700     -     32      -     Off    -      1      -     86      -     42       -     22       -     211      -     206
    129     -      15701     -     32      -     Off    -      1      -     86      -     102      -     124      -     104      -     245
    129     -      15702     -     32      -     Off    -      1      -     86      -     11       -     164      -     250      -     70
    129     -      15703     -     32      -     Off    -      1      -     86      -     194      -     39       -     240      -     162
    129     -      15704     -     32      -     Off    -      1      -     81      -     204      -     32       -     16       -     236
    129     -      15705     -     32      -     Off    -      1      -     81      -     170      -     191      -     255      -     246
    129     -      15706     -     32      -     Off    -      1      -     88      -     92       -     111      -     119      -     147
    129     -      15706     -     32      -     Off    -      1      -     88      -     92       -     111      -     119      -     147
    129     -      15707     -     32      -     Off    -      1      -     88      -     57       -     199      -     122      -     111
    129     -      15708     -     32      -     Off    -      1      -     81      -     59       -     232      -     174      -     231
    129     -      15709     -     32      -     Off    -      1      -     83      -     239      -     157      -     35       -     42
    129     -      15710     -     32      -     Off    -      1      -     84      -     147      -     99       -     114      -     36
    129     -      15711     -     32      -     Off    -      1      -     87      -     170      -     254      -     187      -      8
    129     -      15712     -     32      -     Off    -      1      -     81      -     186      -     210      -     182      -     111
    129     -      15713     -     32      -     Off    -      1      -     84      -     218      -     159      -     55       -     183
    129     -      15714     -     32      -     Off    -      1      -     84      -     232      -     27       -     101      -     197

For easier comparison, I've removed the duplicate lines. In each case, I've pressed the same button, which is the Off button. The first bit is labeled as pairing because when the button is pressed for adding to the receiving device, this changes to another value. Otherwise, it's always 129. Sequence seems to be an unsigned long from bits 2-5, but in reverse order. Button is obvious, it's a different value depending on what button is pressed. While I have no idea what they mean, bits 6 and 8 are always the same. 9 seems to be between 81 and 88 and the rest seem random. I'm sure they're not really random, but I know nothing about even attempting to decipher things like that.

If the developers embedded some sort of anti replay protection or rolling code security or something then it will be hard to exactly get what magic formula they came up with…

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.