Hack The Box Sherlocks - Einladen Writeup - はまやんはまやんはまやん

はまやんはまやんはまやん

hamayanhamayan's blog

Hack The Box Sherlocks - Einladen Writeup

https://app.hackthebox.com/sherlocks/Einladen
Hack The Box Sherlocksとは

Sherlock Scenario

Our staff recently received an invite to the German embassy to bid farewell to the Germany Ambassador. We believe this invite was a phishing email due to alerts that fired on our organisation's SIEM tooling following the receipt of such mail. We have provided a wide variety of artifacts inclusive of numerous binaries, a network capture, DLLs from the host system and also a .hta file. Please analyse and complete the questions detailed below!
私たちのスタッフは最近、ドイツ大使にお別れを告げるためにドイツ大使館への招待状を受け取りました。このようなメールの受信後に組織の SIEM ツールでアラートが発せられたため、この招待状はフィッシング メールであると考えられます。多数のバイナリ、ネットワーク キャプチャ、ホスト システムからの DLL、および .hta ファイルを含む、さまざまなアーティファクトを提供しました。以下に詳しく説明されている質問を分析して回答してください。

色々なアーティファクトが与えられるので解析しながら設問に答えていこう。

Tasks

Task 1

The victim visited a web page.The HTML file of the web page has beenprovided as ‘downloader.html’ sample file.The web page downloadsa ZIP file named 'Invitation_Farewell_DE_EMB.zip'. What is the SHA-256 hash of the ZIP file?
被害者は Web ページにアクセスしました。Web ページの HTML ファイルは、「downloader.html」サンプル ファイルとして提供されています。Web ページは、「Invitation_Farewell_DE_EMB.zip」という名前の ZIP ファイルをダウンロードします。ZIP ファイルの SHA-256 ハッシュは何ですか?

downloader.htmlを開くと変数dでデータがdecimalで入っているので、持ってきてCyberChefに送る。

Task 2

Thedownloaded ZIP file contains a HTA file, which creates multiple files. One of those files is a signed fileby Microsoft Corporation. In HTA file, which variable’s value was the content of that signed file?
ダウンロードした ZIP ファイルには、複数のファイルを作成する HTA ファイルが含まれています。これらのファイルの 1 つは、Microsoft Corporation によって署名されたファイルです。HTA ファイルでは、どの変数の値が署名されたファイルの内容でしたか?

該当htaファイルはInvitation_Farewell_DE_EMB.htaのこと。中

Task 3

The threat actor was acting as an embassy of a country. Which country was that?
攻撃者はある国の大使館として活動していました。それはどこの国でしたか?

PDFの中身を見るとドイツからの資料であることが分かる。

Task 4

The malware communicatedwith a chatting platform domain. What is the domainname (inclusive of sub doamain) the malware connects to?
マルウェアはチャット プラットフォームのドメインと通信しました。マルウェアが接続するドメイン名 (サブドメインを含む) は何ですか?

ネットワーク接続が分かりそうなソースとしてpcapngファイルがあるので見てみよう。DNS通信を見ると怪しいドメインがある。

69   192.168.0.105   51935   192.168.0.1 53  DNS 78          Standard query 0x0f17 A toyy.zulipchat.com

Task 5

How many DNS A records were found for that domain?
そのドメインDNS A レコードがいくつ見つかりましたか?

応答がNo.71として記録されていたので、見てみると6つ応答が帰ってきている。

Task 6

It seems like the chatting service was running on a very known cloud service using a FQDN, where the FQDN contains the IP address of the chatting domain in reversive format somehow. What is the FQDN?
チャット サービスは、FQDN を使用するよく知られたクラウド サービス上で実行されていたようです。FQDN には、チャット ドメインの IP アドレスが何らかの形で逆形式で含まれています。FQDNとは何ですか?

Taks 5と同じDNSでの通信を見ると以下のような応答があり、設問の答えに即してそうなフォーマットになっている。

84   192.168.0.1 53  192.168.0.105   54294   DNS 141         Standard query response 0x3bf0 PTR 55.197.171.35.in-addr.arpa PTR ec2-35-171-197-55.compute-1.amazonaws.com

Task 7

What was the parent PID (PPID) of the malware?
マルウェアの親 PID (PPID) は何でしたか?

Logfile.PMLで細かい情報が得られそうなのでSysInternalsのProcess Monitorで開く。ProcessStartのログを見るとPPIDも記録されているのでそれを答える。

Task 8

What was the computer name of the victim computer?
被害を受けたコンピュータのコンピュータ名は何でしたか?

Logfile.PMLの適当なログに環境変数が残っているので、そこからコンピュータ名が分かる。COMPUTERNAME=DESKTOP-O88AN4O

Task 9

What was the username of the victim computer?
被害者のコンピュータのユーザー名は何でしたか?

これもTaks 8同様に環境変数から分かる。

Task 10

How many times were the Windows Registry keys set with a data value?
Windows レジストリ キーにデータ値が設定された回数は何回ですか?

Logfile.PMLを開き、OperationのRegSetValueでフィルタリングすると11件出てくるのでこれが答え。

Integer, e.g - 65

Task 11

Did the malicious mso.dll load by the malware executable successfully?
悪意のある mso.dll はマルウェア実行可能ファイルによって正常に読み込まれましたか?

Logfile.PMLを開き、OperationのLoad Imageでフィルタリングすると分かる。フィルタリングして見てみるとmso.dllの読み込みにSUCCESSしているのでyes

Task 12

The JavaScript file tries to write itself as a .bat file. What is the .bat file name (name+extension) it tries to write itself as?
JavaScript ファイルは、それ自体を .bat ファイルとして書き込もうとします。それ自体を書き込もうとする .bat ファイル名 (名前 + 拡張子) は何ですか?

unc.jsというファイルが与えられる。難読化を頑張って解除していくと

'return this')()['WScript']['CreateObject']('WScript.Shell')['run']('cmd /k copy "' + this['WScript']['ScriptFullName'] + '" "%temp%\\\\richpear.bat" && "%temp%\\\\richpear.bat"')

こんな感じのコマンド片が得られて、ファイル名が得られる。

Task 13

The JavaScript file contains a big text which is encoded as Base64. If you decode that Base64 text and write its content as an EXE file. What will be the SHA256 hash of the EXE?
JavaScript ファイルには、Base64 としてエンコードされた大きなテキストが含まれています。その Base64 テキストをデコードし、その内容を EXE ファイルとして書き込むとします。EXE の SHA256 ハッシュは何になりますか?

コメント部分にbase64エンコード文字列があるのでそれをデコードして持ってくる。

$ sha256sum unc_bin.bin 
db84db8c5d76f6001d5503e8e4b16cdd3446d5535c45bbb0fca76cfec40f37cc  unc_bin.bin

Task 14

The malware contains a class Client.Settings which sets different configurations. It has a variable ‘Ports’ where the value is Base64 encoded. The value is decrypted using Aes256.Decrypt. After decryption, what will be its value (the decrypted value will be inside double quotation)?
このマルウェアには、さまざまな構成を設定するクラス Client.Settings が含まれています。これには、値が Base64エンコードされた変数「Ports」があります。値は Aes256.Decrypt を使用して復号化されます。復号化後の値はどうなりますか (復号化された値は二重引用符で囲まれます)。

Mono/.Net assemblyだったので、dnSpyで中を見てみる。

public static string Ports = "Yhc6k+R99kweya1xRMDhAdRjrYVuSxpgA2Lefoj5KOsbK3OcJtOpNfDubKUTCiWHoVrnnwqj70kyfYTLboawyVxN0W+L/MRchSITSNbbgXE=";

同じ所に鍵もある。

public static string Key = "d0cyOFJwZlBBSXBnalhEVFd2bEdiVHRkQnpybnRBeVM=";

saltもある。

     private static readonly byte[] Salt = new byte[]
        {
            191,
            235,
            30,
            86,
            251,
            205,
            151,
            59,
            178,
            25,
            2,
            36,
            48,
            165,
            120,
            67,
            0,
            61,
            86,
            68,
            210,
            30,
            98,
            185,
            212,
            241,
            128,
            231,
            230,
            195,
            57,
            65
        };

これを使って、このように鍵を生成。

         using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(masterKey, Aes256.Salt, 50000))
            {
                this._key = rfc2898DeriveBytes.GetBytes(32);
                this._authKey = rfc2898DeriveBytes.GetBytes(64);
            }

復号はこんな感じ。

         byte[] result;
            using (MemoryStream memoryStream = new MemoryStream(input))
            {
                using (AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider())
                {
                    aesCryptoServiceProvider.KeySize = 256;
                    aesCryptoServiceProvider.BlockSize = 128;
                    aesCryptoServiceProvider.Mode = CipherMode.CBC;
                    aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
                    aesCryptoServiceProvider.Key = this._key;
                    using (HMACSHA256 hmacsha = new HMACSHA256(this._authKey))
                    {
                        byte[] a = hmacsha.ComputeHash(memoryStream.ToArray(), 32, memoryStream.ToArray().Length - 32);
                        byte[] array = new byte[32];
                        memoryStream.Read(array, 0, array.Length);
                        if (!this.AreEqual(a, array))
                        {
                            throw new CryptographicException("Invalid message authentication code (MAC).");
                        }
                    }
                    byte[] array2 = new byte[16];
                    memoryStream.Read(array2, 0, 16);
                    aesCryptoServiceProvider.IV = array2;
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aesCryptoServiceProvider.CreateDecryptor(), CryptoStreamMode.Read))
                    {
                        byte[] array3 = new byte[memoryStream.Length - 16L + 1L];
                        byte[] array4 = new byte[cryptoStream.Read(array3, 0, array3.Length)];
                        Buffer.BlockCopy(array3, 0, array4, 0, array4.Length);
                        result = array4;
                    }
                }
            }

これをもとにデコーダを書く。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;

namespace payload
{
    public class Aes256
    {
        // Token: 0x06000072 RID: 114 RVA: 0x000067BC File Offset: 0x000049BC
        public Aes256(string masterKey)
        {
            if (string.IsNullOrEmpty(masterKey))
            {
                throw new ArgumentException("masterKey can not be null or empty.");
            }
            using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(masterKey, Aes256.Salt, 50000))
            {
                this._key = rfc2898DeriveBytes.GetBytes(32);
                this._authKey = rfc2898DeriveBytes.GetBytes(64);
            }
        }

        // Token: 0x06000073 RID: 115 RVA: 0x00003D23 File Offset: 0x00001F23
        public string Encrypt(string input)
        {
            return Convert.ToBase64String(this.Encrypt(Encoding.UTF8.GetBytes(input)));
        }

        // Token: 0x06000074 RID: 116 RVA: 0x00006834 File Offset: 0x00004A34
        public byte[] Encrypt(byte[] input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input can not be null.");
            }
            byte[] result;
            using (MemoryStream memoryStream = new MemoryStream())
            {
                memoryStream.Position = 32L;
                using (AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider())
                {
                    aesCryptoServiceProvider.KeySize = 256;
                    aesCryptoServiceProvider.BlockSize = 128;
                    aesCryptoServiceProvider.Mode = CipherMode.CBC;
                    aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
                    aesCryptoServiceProvider.Key = this._key;
                    aesCryptoServiceProvider.GenerateIV();
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aesCryptoServiceProvider.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        memoryStream.Write(aesCryptoServiceProvider.IV, 0, aesCryptoServiceProvider.IV.Length);
                        cryptoStream.Write(input, 0, input.Length);
                        cryptoStream.FlushFinalBlock();
                        using (HMACSHA256 hmacsha = new HMACSHA256(this._authKey))
                        {
                            byte[] array = hmacsha.ComputeHash(memoryStream.ToArray(), 32, memoryStream.ToArray().Length - 32);
                            memoryStream.Position = 0L;
                            memoryStream.Write(array, 0, array.Length);
                        }
                    }
                }
                result = memoryStream.ToArray();
            }
            return result;
        }

        // Token: 0x06000075 RID: 117 RVA: 0x00003D3B File Offset: 0x00001F3B
        public string Decrypt(string input)
        {
            return Encoding.UTF8.GetString(this.Decrypt(Convert.FromBase64String(input)));
        }

        // Token: 0x06000076 RID: 118 RVA: 0x0000698C File Offset: 0x00004B8C
        public byte[] Decrypt(byte[] input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input can not be null.");
            }
            byte[] result;
            using (MemoryStream memoryStream = new MemoryStream(input))
            {
                using (AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider())
                {
                    aesCryptoServiceProvider.KeySize = 256;
                    aesCryptoServiceProvider.BlockSize = 128;
                    aesCryptoServiceProvider.Mode = CipherMode.CBC;
                    aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
                    aesCryptoServiceProvider.Key = this._key;
                    using (HMACSHA256 hmacsha = new HMACSHA256(this._authKey))
                    {
                        byte[] a = hmacsha.ComputeHash(memoryStream.ToArray(), 32, memoryStream.ToArray().Length - 32);
                        byte[] array = new byte[32];
                        memoryStream.Read(array, 0, array.Length);
                    }
                    byte[] array2 = new byte[16];
                    memoryStream.Read(array2, 0, 16);
                    aesCryptoServiceProvider.IV = array2;
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aesCryptoServiceProvider.CreateDecryptor(), CryptoStreamMode.Read))
                    {
                        byte[] array3 = new byte[memoryStream.Length - 16L + 1L];
                        byte[] array4 = new byte[cryptoStream.Read(array3, 0, array3.Length)];
                        Buffer.BlockCopy(array3, 0, array4, 0, array4.Length);
                        result = array4;
                    }
                }
            }
            return result;
        }

        // Token: 0x04000038 RID: 56
        private const int KeyLength = 32;

        // Token: 0x04000039 RID: 57
        private const int AuthKeyLength = 64;

        // Token: 0x0400003A RID: 58
        private const int IvLength = 16;

        // Token: 0x0400003B RID: 59
        private const int HmacSha256Length = 32;

        // Token: 0x0400003C RID: 60
        private readonly byte[] _key;

        // Token: 0x0400003D RID: 61
        private readonly byte[] _authKey;

        // Token: 0x0400003E RID: 62
        private static readonly byte[] Salt = new byte[]
        {
            191,
            235,
            30,
            86,
            251,
            205,
            151,
            59,
            178,
            25,
            2,
            36,
            48,
            165,
            120,
            67,
            0,
            61,
            86,
            68,
            210,
            30,
            98,
            185,
            212,
            241,
            128,
            231,
            230,
            195,
            57,
            65
        };
    };

    public class Run
    {

        static void Main(string[] args)
        {
            Console.WriteLine("Main");
            var key = "d0cyOFJwZlBBSXBnalhEVFd2bEdiVHRkQnpybnRBeVM=";
            key = Encoding.UTF8.GetString(Convert.FromBase64String(key));
            var aes = new Aes256(key);
            var enc = "Yhc6k+R99kweya1xRMDhAdRjrYVuSxpgA2Lefoj5KOsbK3OcJtOpNfDubKUTCiWHoVrnnwqj70kyfYTLboawyVxN0W+L/MRchSITSNbbgXE=";
            var res = aes.Decrypt(enc);
            Console.WriteLine(res);
        }
    };
}

Task 15

The malware sends a HTTP request to a URI and checks the country code or country name of the victim machine. To which URI does the malware sends request for this?
マルウェアは HTTP リクエストを URI に送信し、被害者のマシンの国コードまたは国名をチェックします。マルウェアはこのリクエストをどの URI に送信しますか?

Client.Helper.GetCountryNameを見ると処理が分かり、 使われているURIもわかる。

Task 16

After getting the country code or country name of the victim machine, the malware checks some country codes and a country name. In case of the country name, if the name is matched with the victim machine’s country name, the malware terminates itself. What is the country name it checks with the victim system?
マルウェアは、被害者のマシンの国コードまたは国名を取得した後、いくつかの国コードと国名をチェックします。国名の場合、その名前が被害者のマシンの国名と一致すると、マルウェアは自動的に終了します。被害者システムでチェックされる国名は何ですか?

     public static void GetSNG()
        {
            string countryCode = Antisng.GetCountryCode();
            string countryName = Antisng.GetCountryName();
            if (countryCode == "RU" || countryCode == "AZ" || countryCode == "AM" || countryCode == "BY" || countryCode == "KZ" || countryCode == "KG" || countryCode == "MD" || countryCode == "TJ" || countryCode == "TM" || countryCode == "UZ" || countryName == "Russia")
            {
                Environment.Exit(0);
            }
        }

ここでチェックしている。明示的に国名が書かれているのはRussia

Task 17

As an anti-debugging functionality, the malware checks if there is any process running where the process name is a debugger. What is the debugger name it tries to check if that’s running?
アンチデバッグ機能として、マルウェアはプロセス名がデバッガーであるプロセスが実行されているかどうかをチェックします。実行中かどうかを確認しようとするデバッガの名前は何ですか?

     public static void RunAntiAnalysis()
        {
            if (Anti_Analysis.DetectManufacturer() || Anti_Analysis.DetectDebugger() || Anti_Analysis.DetectSandboxie() || Anti_Analysis.IsSmallDisk() || Anti_Analysis.IsXP() || Anti_Analysis.IsProcessRunning("dnSpy") || Anti_Analysis.CheckWMI())
            {
                Environment.FailFast(null);
            }
        }

というプログラムが見つかる。dnSpy

Task 18

For persistence, the malware writes a Registry key where the registry key is hardcoded in the malware in reversed format. What is the registry key after reversing?
永続性を維持するために、マルウェアレジストリ キーを書き込みます。レジストリ キーはマルウェア内で逆形式でハードコーディングされています。元に戻した後のレジストリ キーは何ですか?

Client.Install.NormalStartupに以下のようにある。

using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(Strings.StrReverse("\\nuR\\noisreVtnerruC\\swodniW\\tfosorciM\\erawtfoS"), RegistryKeyPermissionCheck.ReadWriteSubTree))

逆にして、CurrentUserのレジストリなのでHKCU\を先頭につけると答え。

Task 19

The malware sets a scheduled task. What is the Run Level for the scheduled task/job it sets?
マルウェアはスケジュールされたタスクを設定します。設定されるスケジュールされたタスク/ジョブの実行レベルは何ですか?

/c schtasks /create /f /sc onlogon /rl highest /tn \"というリテラルがあるので、以下が答え。