SeeTheSharpFlag
3 minutes to read
We are given an APK file (com.companyname.seethesharpflag-x86.apk
). From the name of the challenge, we might think of C# for mobile development. We can start by running MobSF. Once the APK is loaded, we have this screen:
Xamarin Forms
We see that is is built using Xamarin Forms (C# under the hoods). The Java decompiled files are obfuscated, so we need to find another way to reverse the app:
We can extract the files that are inside the APK archive:
$ apktool d com.companyname.seethesharpflag-x86.apk
I: Using Apktool 2.6.1 on com.companyname.seethesharpflag-x86.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: ~/.local/share/apktool/framework/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
$ ls com.companyname.seethesharpflag-x86
AndroidManifest.xml lib res unknown
apktool.yml original smali
$ ls com.companyname.seethesharpflag-x86/unknown
assemblies
There is a directory called assemblies
that holds some DLL compiled in C#. In particular, we are interested in one called SeeTheSharpFlag.dll
.
C# decompilation
After doing some research on Xamarin Forms APK reverse engineering we find that we can use JetBrains dotPeek to decompile the DLL to C# source code. However, we must uncompress the DLL first using a Python script called Xamarin_XALZ_decompress.py (it needs a library called lz4
, which can be installed with pip
):
$ python3 Xamarin_XALZ_decompress.py
usage: ./command compressed-inputfile.dll uncompressed-outputfile.dll
$ python3 Xamarin_XALZ_decompress.py com.companyname.seethesharpflag-x86/unknown/assemblies/SeeTheSharpFlag.dll SeeTheSharpFlag_uncompressed.dll
header index: b'\x05\x00\x00\x00'
compressed payload size: 6005 bytes
uncompressed length according to header: 10240 bytes
result written to file
Once we load the uncompressed DLL in JetBrains dotPeek, we can see the whole C# source code. There is a class called MainPage
that has some interesting stuff:
// Decompiled with JetBrains decompiler
// Type: SeeTheSharpFlag.MainPage
// Assembly: SeeTheSharpFlag, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 98A567F9-AFF4-40D1-9519-780A01746EE7
// Assembly location: .\SeeTheSharpFlag_uncompressed.dll
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Xml;
using Xamarin.Forms;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Xaml;
using Xamarin.Forms.Xaml.Diagnostics;
using Xamarin.Forms.Xaml.Internals;
namespace SeeTheSharpFlag
{
[XamlFilePath("MainPage.xaml")]
public class MainPage : ContentPage
{
[GeneratedCode("Xamarin.Forms.Build.Tasks.XamlG", "2.0.0.0")]
private Label SecretOutput;
[GeneratedCode("Xamarin.Forms.Build.Tasks.XamlG", "2.0.0.0")]
private Editor SecretInput;
public MainPage() => this.InitializeComponent();
private void Button_Clicked(object sender, EventArgs e)
{
byte[] buffer = Convert.FromBase64String("sjAbajc4sWMUn6CHJBSfQ39p2fNg2trMVQ/MmTB5mno=");
byte[] rgbKey = Convert.FromBase64String("6F+WgzEp5QXodJV+iTli4Q==");
byte[] rgbIV = Convert.FromBase64String("DZ6YdaWJlZav26VmEEQ31A==");
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";
}
}
}
}
}
}
// ...
}
}
Basically, it uses AES do decrypt data in a variable called buffer
using rgbKey
as key and rgbIV
as IV.
Flag
Let’s replicate the decryption code in PowerShell:
PS ... \SeeTheSharpFlag> $buffer = [System.Convert]::FromBase64String('sjAbajc4sWMUn6CHJBSfQ39p2fNg2trMVQ/MmTB5mno=')
PS ... \SeeTheSharpFlag> $rgbKey = [System.Convert]::FromBase64String('6F+WgzEp5QXodJV+iTli4Q==')
PS ... \SeeTheSharpFlag> $rgbIV = [System.Convert]::FromBase64String('DZ6YdaWJlZav26VmEEQ31A==')
PS ... \SeeTheSharpFlag> $aesManaged = [System.Security.Cryptography.AesManaged]::new()
PS ... \SeeTheSharpFlag> $decryptor = $aesManaged.CreateDecryptor($rgbKey, $rgbIV)
PS ... \SeeTheSharpFlag> $memoryStream = [System.IO.MemoryStream]::new($buffer)
PS ... \SeeTheSharpFlag> $cryptoStream = [System.Security.Cryptography.CryptoStream]::new($memoryStream, $decryptor, [System.Security.Cryptography.CryptoStreamMode]::Read)
PS ... \SeeTheSharpFlag> $streamReader = [System.IO.StreamReader]::new($cryptoStream)
PS ... \SeeTheSharpFlag> $streamReader.ReadToEnd()
HTB{MyPasswordIsVerySecure}