SeeTheSharpFlag
3 minutos de lectura
Se nos proporciona un archivo APK (com.companyname.seethesharpflag-x86.apk
). A partir del nombre del reto, podemos pensar en C# para desarrollo móvil. Podemos comenzar ejecutando MobSF. Una vez que tenemos el archivo APK cargado, tenemos esta pantalla:
Xamarin Forms
Aquí se ve que está desarrollada con Xamarin Forms (C# por detrás). Los archivos descompilados en Java están ofuscados, por lo que necesitamos encontrar otra manera de realizar ingeniería inversa:
Podemos extraer los archivos incluidos en el APK con apktool
:
$ 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
Hay un directorio llamado assemblies
que contiene algunas DLL compiladas en C#. En concreto, nos interesa una llamada SeeTheSharpFlag.dll
.
Descompilación de C#
Después de realizar un poco de investigación sobre ingeniería inversa en aplicaciones de Xamarin Forms, vemos que tenemos que emplear JetBrains dotPeek para descompilar la DLL a código fuente C#. Sin embargo, tenemos que descomprimir la DLL primero usando un script en Python llamado Xamarin_XALZ_decompress.py (necesita una librería llamada lz4
, que se puede instalar con 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
Una vez que cargamos la DLL descomprimida en JetBrains dotPeek, vemos el código fuente completo en C#. Existe una clase llamada MainPage
que tiene cosas interesantes:
// 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";
}
}
}
}
}
}
// ...
}
}
Básicamente, utiliza AES para descifrar una variable llamada buffer
usando rgbKey
como clave y rgbIV
como IV.
Flag
Vamos a replicar el código de descifrado en 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}