Post

HackTheBox: SeeTheSharpFlag

HackTheBox: SeeTheSharpFlag

Introduction

Android applications come in various frameworks, including Flutter, Xamarin, Cordova, React Native, and more. In this article, I will walk you through a Static Application Security Testing (SAST) approach for a Xamarin Android application by solving an HTB challenge.

Initial Analysis

Upon launching the application, I noticed an input field that accepts a password and validates it. Entering any random password resulted in an error message.

Examining the APK

By analyze the application further, I decompiled the APK using JADX.I found a basic AndroidManifest.xml file:

However, searching for the validation logic in the source code did not yield immediate results. Instead, I observed multiple files and folders related to Xamarin.


Understanding Xamarin.Android Architecture

Xamarin.Android allows developers to build Android applications using C# .NET. The C# code is compiled into Intermediate Language (IL), which is then Just-In-Time (JIT) compiled to a native assembly when the application lucnch. Below is a rough architecture of Xamarin.Android:

  • Xamarin provides .NET bindings to Android.* and Java.* namespaces.
  • Applications run under the Mono execution environment alongside the Android Runtime (ART).
  • Managed Callable Wrappers (MCW) and Android Callable Wrappers (ACW) facilitate communication between the Mono and ART environments.

Locating the Application Logic

Since the application logic is compiled into native libraries, I needed to find these files. Using apktool, I discovered the .dll files under /unknown/assemblies. With JADX, they were found in resources/assemblies/:

Note: The challenge name is SeeTheSharpFlag, hinted at investigating SeeTheSharpFlag.dll.

After downloading the file, I used the file command in Kali Linux to inspect its type. Surprisingly, it was identified as a Sony PlayStation Audio file.

To analyze further, I ran the xxd command and identified a file signature corresponding to XALZ, which is a compressed format used in .NET applications. I then used the xamarin-decompress tool to decompress the library using LZ4 block After decompression, running the file command again revealed it as a Portable Executable 32-bit (PE32) file. I then opened the file using dotPeek, it was a .NET decompiler tool.


Extracting the Password Validation Logic

Upon inspecting SeeTheSharpFlag.dll in dotPeek, I found a MainPage class containing a method named Button_Clicked(), which likely handles password validation.

Here’s the extracted function:

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
private void Button_Clicked(object sender, EventArgs e)
    {
      byte[] buffer = Convert.FromBase64String("sjAbajc4sWMUn6HJBSfQ39p2fNg2trMQ/MmTB5mno=");
      byte[] rgbKey = Convert.FromBase64String("6F+WzEp5QXoJV+iTli4Q==");
      byte[] rgbIV = Convert.FromBase64String("DZ6YaWJlZ26VmEEQ31A==");
      using (AesManaged aesManaged = new AesManaged())
      {
        using (ICryptoTransform decryptor = aesManaged.CreateDecryptor(rgbKey, rgbIV))
        {
          using (MemoryStream memoryStream = new MemoryStream(buffer))
          {
            using (CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read))
            {
              using (StreamReader streamReader = new StreamReader((Stream) cryptoStream))
              {
                if (streamReader.ReadToEnd() == ((InputView) this.SecretInput).Text)
                  this.SecretOutput.Text = "Congratz! You found the secret message";
                else
                  this.SecretOutput.Text = "Sorry. Not correct password";
              }
            }
          }
        }
      }
    }

From this code, we can see that the application uses AES encryption to validate the password through this line:

1
if (streamReader.ReadToEnd() == ((InputView) this.SecretInput).Text)

Also The decryption keys are hardcoded in the application, making it possible to decrypt the expected password.

1
2
3
byte[] buffer = Convert.FromBase64String("sjAbajc4sWMUn6HJBSfQ39p2fNg2trMQ/MmTB5mno=");
byte[] rgbKey = Convert.FromBase64String("6F+WzEp5QXoJV+iTli4Q==");
byte[] rgbIV = Convert.FromBase64String("DZ6YaWJlZ26VmEEQ31A==");

Decrypting the Password

The AES encryption used in the application employs CBC mode with Base64-encoded components. Below is a Python script to decrypt the expected password:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import base64
from Crypto.Cipher import AES

def decrypt_aes_cbc(ciphertext_b64, key_b64, iv_b64):
    ciphertext = base64.b64decode(ciphertext_b64)
    key = base64.b64decode(key_b64)
    iv = base64.b64decode(iv_b64)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted = cipher.decrypt(ciphertext)
    pad_len = decrypted[-1]
    decrypted = decrypted[:-pad_len]
    return decrypted.decode()

ciphertext_b64 = "sjAbajc4sWMUn6HJBSfQ39p2fNg2trMQ/MmTB5mno="
key_b64 = "6F+WzEp5QXoJV+iTli4Q=="
iv_b64 = "DZ6YaWJlZ26VmEEQ31A=="

plaintext = decrypt_aes_cbc(ciphertext_b64, key_b64, iv_b64)
print("========================")
print("==== Decrypted text:", plaintext)
print("========================")

Extracting the Flag

Running the script successfully decrypted the flag. I then submitted it through the mobile app and received the Congratz message.


Conclusion

This challenge demonstrated how to analyze and reverse-engineer Xamarin applications using SAST techniques. By understanding Xamarin’s architecture and extracting native libraries.


For further reading, I highly recommend Akshay Shinde’s blog post on Xamarin Reverse Engineering.

THANKS FOR READING ❤️

This post is licensed under CC BY 4.0 by the author.