28
2024
11
15:58:22

Reversing ArubaOS Firmware and Licensing

References

  1. ios_padding/" style="margin: 0px; padding: 0px; text-decoration-line: none; background-color: transparent; transition: color 0.3s ease 0s; box-sizing: border-box; border-bottom: 1px solid var(--color-text-a); font-size: 1em;">一种获取 FortiGate 权限的方法 & License 授权分析 - CataLpa: This blog post reverse-engineered the FortiGate firmware and licensing mechanism, and published a tool to generate the license keys.

  2. Reversing ArubaOS Firmware - SerializingMe: This blog post explores the ArubaOS firmware using Binwalk, but it doesn’t go into the details.

  3. Bypass-Insecure-Transport-Tons-Of-Issues.html" style="margin: 0px; padding: 0px; text-decoration-line: none; background-color: transparent; transition: color 0.3s ease 0s; box-sizing: border-box; border-bottom: 1px solid var(--color-text-a); font-size: 1em;">Aruba Authentication Bypass / Insecure Transport / Tons Of Issues ≈ Packet Storm: This blog post published a collection of vulnerabilities in ArubaOS, including arbitrary modification of /etc/ntp.conf, static password of privileged “support” account and hardcoded “arubasecretadmin” account in /etc/passwd. The most important part is:

    1. It says the IV required for 3DES consists of 8
      random bytes, and is stored as the first 8 byte of the encrypted password
      , which may also be used in ArubaOS for lisensing mechanism, I guess.

    2. It leaked the hardcoded 3DES key in the firmware.

  4. Remote Code Execution in Aruba Mobility Controller (ArubaOS) - CVE-2018-7081: This blog post describes simulating the ArubaOS in QEMU and intercepting the communication of PAPI.

Exploration

By chance, I obtained a brand new Aruba 650 controller with full licenses, at a few years ago with an irresistible price. The licensing mechanism is complete off-line, which means that all necessary information is hashed/encoded as a part of the license key, including the serial number, feature set, expiration date, and so on.

  • Device serial number: AR00XXXXX

  • License: XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXX

    • Length with hyphens: 48

    • Length without hyphens: 43

    • Length of license without hyphens in base64: 64

1
2
3
filename: ArubaOS_6xx_6.4.4.25_79899
SHA-1: defbb8709b90b14c4f78fa5ae64b0c39276d90df
MD5: f038d7810c4f036005a6a4ef86a18137

By simply running binwalk -re --dd=".*" ArubaOS_6xx_6.4.4.25_79899, we can extract the firmware from the image.

1
2
3
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
512           0x200           ELF, 32-bit MSB MIPS-IV executable, MIPS, version 1 (SYSV)

Then, do the same thing for the extracted ELF file 200binwalk -e 200, now we obtained a compressed file 5B4000.7z. On Windows 10, we can use Bandizip to extract it, and we got a core_image_files.tar, which is the root filesystem of the ArubaOS. This step seems cannot be done on macOS, for unknown reasons. The file tree is attached.

As for its name, core_image_files/mswitch/bin/licensemgr, it seems to be the license manager of the ArubaOS. Based on the existing knowledge and with the help of ChatGPT, we can perform deobfucation to some extent.

1
2
3
filename: licensemgr
SHA-1: a3f12c8357297a361ec3d112313aa4cc8af0e7e0
MD5: be48ae6c4cb5822885237001a847f2d9

By looking into IDA, we have the pseudo code as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
_BYTE *__fastcall _license_user_to_base64(char *a1, int a2)
{
   char v2;       // $v1
   int v4;        // $v0
   int i;         // $a1
   _BYTE *v6;     // $a2
   int v7;        // $v1
   int v8;        // $v1
   _BYTE *result; // $v0

   v2 = *a1;
   v4 = *a1;
   for (i = 0; *a1; v4 = *a1)
   {
       v6 = (_BYTE *)(i + a2);
       if (v4 != 45)
       {
           ++i;
           *v6 = v2;
       }
       v2 = *++a1;
   }
   if (i == 32)
       goto LABEL_10;
   v7 = 1;
   if (i != 43)
       v7 = 6 - i % 6;
   v8 = v7 - 1;
   result = (_BYTE *)(a2 + i);
   if (v8 != -1)
   {
       do
       {
           --v8;
           *(_BYTE *)(i + a2) = 61;
           ++i;
       } while (v8 != -1);
   LABEL_10:
       result = (_BYTE *)(a2 + i);
   }
   *result = 0;
   return result;
}

With the help of ChatGPT, we obtained the following deobfuscated code, with some comments generated by ChatGPT as well:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// Function to convert a string to base64 with certain conditions
// Parameters:
// - a1: Input string
// - a2: Base address for output

_BYTE *__fastcall _license_user_to_base64(char *a1, int a2)
{
   char currentChar; // Current character in the input string
   int i;            // Counter for the loop
   _BYTE *output;    // Pointer to the output buffer
   int paddingCount; // Number of '=' padding characters to be added

   currentChar = *a1;          // Initialize currentChar with the first character of the input string
   i = 0;                      // Initialize the loop counter
   output = (_BYTE *)(i + a2); // Initialize the output pointer based on the provided base address

   // Iterate through the characters of the input string
   while (*a1)
   {
       // If the current character is not '-', copy it to the output buffer
       if (currentChar != 45)
       {
           ++i;                   // Increment the counter
           *output = currentChar; // Copy the character to the output buffer
       }
       currentChar = *++a1; // Move to the next character in the input string
   }

   // Check if the total count is 32
   if (i == 32)
       goto LABEL_10;

   // Calculate the number of '=' padding characters to be added
   paddingCount = 1;
   if (i != 43) // the length without hyphens
       paddingCount = 6 - i % 6;

   // Add the required '=' padding characters to the output buffer
   while (paddingCount != -1)
   {
       --paddingCount;
       *(_BYTE *)(i + a2) = 61; // '=' character
       ++i;                     // Increment the counter
   }

LABEL_10:
   result = (_BYTE *)(a2 + i); // Set the result pointer to the end of the output buffer
   *result = 0;                // Null-terminate the output buffer
   return result;              // Return the result pointer
}

So basically, it removes the hyphens from the input string, and adds padding for making it as a valid base64 string. By checking XREF information, we can found that this function is called by _license_decrypt_bundle_key_license_decrypt_feature_key and _license_decrypt_platform_key.

Let’s focus on _license_decrypt_bundle_key first, it first calls _license_user_to_base64 to convert the input string to base64, then calls _license_str_to_byte to convert the base64 string to byte array and check format validity, and finally calls _license_decrypt to decrypt the byte array.

1
license_decrypt((int)licenseInBytes, lic_b64_length_int_64 / 2, (int)output, 51)

Since then I stucked, the _license_base64_dec is so complicated.




推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

本文链接:https://www.hqyman.cn/post/8664.html 非本站原创文章欢迎转载,原创文章需保留本站地址!

分享到:
打赏





休息一下~~


« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

请先 登录 再评论,若不是会员请先 注册

您的IP地址是: