CRACKING THE AES ENCRYPTION HARDCODED KEY OF THE KANKUN SMART PLUG
- Layout for this exercise:
1 - Introduction
- This exercise is based on the two previous posts related with the Kankun Smart Plug:
https://dgmsp.blogspot.com/2017/05/11-extracting-and-analyzing-firmware-of.html
https://dgmsp.blogspot.com/2017/05/12-cracking-root-password-and.html
- The Kankun Smart Plug communicates with a smartphone or mobile device over UDP port 27431, using an AES key that is hardcoded in its firmware.
- The vulnerability is registered here:
https://packetstormsecurity.com/files/132210/Kankun-Smart-Socket-Mobile-App-Hardcoded-AES-Key.html
- Let's go to the application smartwifi.apk:
- Unzipping the application:
- Updating the internal database of Ubuntu:
- Locating the native ARM code of the application (shared object library libNDK_03.so) inside the unzipped folder:
- Determining the type of the file, it is an ARM architecture intended application:
- Reading the headers, we also notice that it uses little endian format:
2 - Using the "strings" command to find the hardcoded key
- One of the problems of hardcoding a key and storing it as a string is that it can be easily discovered.
- For instance, applying the command strings over the shared object library libNDK_03.so several strings starting with AES are discovered, giving us a hint that the AES encryption is used. For instance, aes_set_key or aes_encrypt:
...
...
- Redirecting the output of the command strings to a text file:
- Now, using a Python script we can detect up to four strings starting with AES inside the text file, meaning that the AES algorithm encryption is very probably used:
- The AES algorithm uses three possible different key lengths: 128, 192 and 256 bits (16, 24 and 32 Bytes).
https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
- So, the possible AES keys must be of either 16, 24, or 32 Bytes length. Let's use a Python script for finding strings of those sizes (plus 1, because in the text file the strings end up with a return line character).
- First, let's suppose that the key is of 256 bits (32 Bytes = 33 characters including the last return line). Two strings of that length are discovered. The first one is just a system string, so the second one could be a good candidate to be the AES key:
- Using the same Python scripts for sizes of 16 Bytes and 24 Bytes, the result is that all the discovered strings are system strings, so we can conclude that the 32 Bytes key discovered before is being used (fdsl;mewrjope4...)
- An attacker could use this key to intercept the communication between the Kankun Smart Plug and a wirelessly connected device (as we will do in the next post).
- Now, let's disassemble the application with IDA, using its evaluation version for Linux:
- Once extracted to Ubuntu:
- Launching IDA with ./idaq:
- Selecting libNDK_03.so:
- The processor to be set is ARM Little-endian:
- Going to the function aes_set_key:
- Searching for strings:
- Again, the same string than before is discovered:
- However, let's explore in a deeper way the application.
- The Java Native Interface (JNI) is a programming framework that enables Java code running in a Java Virtual Machine (JVM) to call and be called by[1] native applications (programs specific to a hardware and operating system platform) and libraries written in other languages such as C, C++ and assembly.
https://en.wikipedia.org/wiki/Java_Native_Interface
- Going to the package of the application (hangzhou, see previous posts), let's find everything related with the pattern 'jni', using the command grep (-i = ignore case distinctions, -R = recursively, -n = line numbering):
- Disassembling with IDA the encoding function Java_hangzhou_kankun_WifiJniC_encode:
- At address 0x000039B8 there is a function called EncryptData:
- Clicking the function EncryptData, IDA opens its code:
- Because we are dealing with ARM assembly language, it is important to remember that R0, R1, R2, R3 are the registers where the parameters are loaded before calling a subroutine.
- Checking the content of R3, IDA offers the option of calculating it directly, just clicking over the instruction:
- So, 0x3E96 is the content of R3 at this point:
- Then, PC (Program Counter, next instruction to be fetched, in this case 0x384E) is loaded over R3, and finally adding 0x28:
- Eventually, the content of R3 will be 0x3E96 + 0x384E + 0x28:
- The result of the sum is 0x770C:
- Jumping to 0x770C, the AES key is again discovered there:
- Now, let's explore the function aes_set_key:
- The signature of the function indicates that 3 parameters are passed. The first is the AES context (loaded into R0), the second is the AES key itself (loaded into R1), and the third is the size of the AES key (loaded into R2):
- Let's see what happens with the size of the AES key, examining the final content of R2.
- The initial value loaded into R2 is (0x80 = 128). However, the instruction LSLS (Logical Shift Left) shifts 1 bit to the left, meaning multiplying by 2:
- From 0x80 (128 decimal) to 0x100 (256 decimal):
- The LSLS bitwise operation just shift the bits one position to the left. From the binary 10000000 (128 decimal) to 100000000 (256 decimal)
- Again, we can conclude that the AES key size used by the Kakun Smart Plug is of 256 bits.