FWE CTF 2025 - Writeup
Writeup for challenges from Foobar CTF 2025 held by Team Aavishkar.
CTFTime: https://ctftime.org/event/2864 โ
Table of Contents
| Category | Name | Diff |
|---|---|---|
| Misc | Poison Apple | Beginner |
| Crypto | baby-crypto | Beginner |
| base-๐ | Easy | |
| Rev | strings jacking | Beginner |
| No need Logical Thinking | Easy | |
| Web Exploit | regex-auth | Beginner |
| Foren/osint | datamosh | Beginner |
| RSA Phone Tree | Medium | |
| EXIT | Medium | |
| GeoGuessr1 | Beginner | |
| GeoGuessr2 | Easy |
โจ Misc#
Poison Apple#
Description
iOSใงใฏใฆใฉใใใใใฐใฟใคใใๆ ้ใใๆใซ่ฟใฃใฆใใไธๆ่ญฐใช4ใใคใใใใใใใโฆ ๅคงๆๅญใซใใฆfwectfใงๅฒใฃใฆใญ ไพ:1234ABCDโfwectf{1234ABCD}
Apparently, there are four special bytes returned when the watchdog timer fails on iOSโฆ Capitalize them and enclose them in fwectf. e.g.1234ABCDโfwectf{1234ABCD}
Solve So, basically i just have to search about this challenge. Itโs all about iOS special bytes that is returned when the wathcdog timer fails on it. I just found it on appleโs documentation here โ. It said
Exception Type: EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00dtxtSo, the flag is 8badf00d wrapped and capitalized. Flag:
fwectf{8BADF00D}sh๐ Crypto#
baby-crypto#
Description
sjrpgs{ebg13rq_zrffntr!} Solve Just decode it with rot13 decoder like rot13.com โ
Flag:
fwectf{rot13ed_message!}shbase-๐#
Description
๐ช๐ฑ๐๐ซ๐๐๐๐ฉ๐๐๐ฌ๐งจ๐ฑ๐ฅ๐ซ๐งถ๐ช๐ฑ๐๐ง๐๐๐๐ฉ๐๐ก๐ฌ๐งฎ๐คฎ๐ฅ๐ซ๐๐ช๐ฑ๐ฝ๐ง๐๐ป๐ณ๐ฉ๐ฅ๐ชจ๐ฌ๐ฉฐ๐๐ฅ๐ซ๐ช๐ช๐ฑ๐ฟ๐ซ๐๐ต๐๐ฉ๐๐๐ฌ๐งฏ๐บ๐ฅ๐ซ๐๐ช๐ฐ๐๐ซ๐๐ฟ๐ณ๐ฉ๐ฒ๐๐ฌ๐งฒ๐ฏ๐ฅ๐ซ๐ฐ๐ช๐ฑ๐๐ง๐๐๐ผ๐ฉ๐ฟ๐ชป๐ฌ๐งช๐๐ฅ๐ซ๐งข๐ช๐ฑ๐๐ง๐๐๐ซณ๐ฉ๐๐๐ฌ๐งถ๐๐ฅ๐ซ ๐๐ช๐ฑ๐๐๐๐๐ฅ๐ฉ๐ฑ๐คฎ๐ฌ๐ฉฐ๐ณ๐ฅ๐ซ๐๐ช๐ฐ๐ฝ๐ซ๐๐ฟ๐๐ฉ๐๐๐ฌ๐งต๐ท๐๐๐
Solve So, i got the chall.py and emoji.txt
#!/usr/bin/env python๐
with open('emoji.txt', 'r', encoding='utf-8') as f:
emoji = list(f.read().strip())
table = {i: ch for i, ch in enumerate(emoji)}
def encode(data):
bits = ''.join(f'{b:08b}' for b in data)
pad = (-len(bits)) % 10
bits += '0' * pad
out = [table[int(bits[i:i+10], 2)] for i in range(0, len(bits), 10)]
r = (-len(out)) % 4
if r:
out.extend('๐' * r)
return ''.join(out)
if __name__ == '__main__':
msg = 'Hello!'
enc = encode(msg.encode())
print('msg:', msg)
print('enc:', enc)pythonโญโญ๐๐๐๐๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ค๐ฅ๐ฆ๐ง๐จ๐ฉ๐ช๐ฌ๐ญ๐ฎ๐ฏ๐ฐ๐ฑ๐ฒ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐น๐บ๐ป๐ผ๐ฝ๐พ๐ฟ๐๐๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ข๐ฃ๐ค๐ฅ๐ฆ๐ง๐จ๐ฉ๐ช๐ซ๐ฌ๐ญ๐ฎ๐ฏ๐ฐ๐ฑ๐ฒ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐น๐บ๐ป๐ผ๐ฝ๐พ๐ฟ๐๐๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ข๐ฃ๐ค๐ฅ๐ฆ๐ง๐จ๐ฉ๐ช๐ซ๐ฌ๐ญ๐ฎ๐ฏ๐ฐ๐ฑ๐ฒ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐น๐บ๐ป๐ผ๐ฝ๐พ๐ฟ๐๐๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ข๐ฃ๐ค๐ฅ๐ฆ๐ง๐จ๐ช๐ซ๐ฌ๐ญ๐ฎ๐ฏ๐ฐ๐ณ๐ด๐ต๐ท๐ธ๐น๐บ๐๐๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ข๐ฃ๐ค๐ฅ๐ฆ๐ง๐จ๐ฉ๐ช๐ซ๐ฌ๐ญ๐ฎ๐ฏ๐ฐ๐ฑ๐ฒ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐น๐บ๐ป๐ผ๐ฝ๐พ๐ฟ๐๐๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ข๐ฃ๐ค๐ฅ๐ฆ๐ง๐จ๐ฉ๐ช๐ซ๐ฌ๐ญ๐ฎ๐ฏ๐ฐ๐ฑ๐ฒ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐น๐บ๐ป๐ผ๐ฝ๐พ๐ฟ๐๐๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ข๐ฃ๐ค๐ฅ๐ฆ๐ง๐จ๐ฉ๐ช๐ซ๐ฌ๐ญ๐ฎ๐ฏ๐ฐ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐น๐บ๐ป๐ผ๐ฝ๐พ๐ฟ๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ข๐ฃ๐ฆ๐ง๐จ๐ช๐ฎ๐ฏ๐ฐ๐ฑ๐ฒ๐ต๐ถ๐ท๐ธ๐น๐บ๐ป๐ผ๐ฝ๐ฟ๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ฅ๐ฆ๐ง๐จ๐ฉ๐ช๐ซ๐ฌ๐ญ๐ฎ๐ฏ๐ฐ๐ฑ๐ฒ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐น๐บ๐ป๐ผ๐ฝ๐๐๐๐๐๐๐๐ฏ๐ฐ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐น๐บ๐๐๐๐๐๐๐๐๐ค๐ฅ๐จ๐ฑ๐ฒ๐ผ๐๐๐๐๐๐๐๐๐๐ก๐ฃ๐จ๐ฏ๐ณ๐บ๐ป๐ผ๐ฝ๐พ๐ฟ๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐ก๐ข๐ฅ๐จ๐ช๐ซ๐ฌ๐ญ๐ฎ๐ฐ๐ฑ๐ณ๐ต๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐
๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ข๐ฃ๐ค๐ฅ๐ฆ๐ง๐จ๐ฉ๐ช๐ซ๐ฌ๐ญ๐ฎ๐ฏ๐ฐ๐ฑ๐ฒ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐ฝ๐ฟ๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐ ๐ก๐ฃ๐ค๐ฅ๐ฉ๐ซ๐ฌ๐ฐ๐ณ๐ด๐ต๐ถ๐ท๐ธ๐น๐บ๐ป๐ผ๐ ๐ก๐ข๐ฃ๐ค๐ฅ๐ฆ๐ง๐จ๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค๐ค ๐คก๐คข๐คฃ๐คฆ๐คง๐คฉ๐คช๐คฌ๐คฎ๐คฏ๐คฐ๐คฑ๐คฒ๐คณ๐คด๐คต๐คถ๐คท๐คธ๐คน๐คบ๐คผ๐คฝ๐คพ๐คฟ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ
๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ๐ฅ ๐ฅก๐ฅข๐ฅฃ๐ฅค๐ฅฅ๐ฅฆ๐ฅง๐ฅจ๐ฅฉ๐ฅช๐ฅซ๐ฅฌ๐ฅญ๐ฅฎ๐ฅฏ๐ฅฐ๐ฅฒ๐ฅณ๐ฅด๐ฅต๐ฅถ๐ฅท๐ฅธ๐ฅน๐ฅบ๐ฅป๐ฅผ๐ฅฝ๐ฅพ๐ฅฟ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ
๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ๐ฆ ๐ฆก๐ฆข๐ฆฃ๐ฆค๐ฆฅ๐ฆฆ๐ฆง๐ฆจ๐ฆฉ๐ฆช๐ฆซ๐ฆฌ๐ฆญ๐ฆฎ๐ฆฏ๐ฆฐ๐ฆฑ๐ฆฒ๐ฆณ๐ฆด๐ฆต๐ฆถ๐ฆท๐ฆธ๐ฆน๐ฆบ๐ฆป๐ฆผ๐ฆฝ๐ฆพ๐ฆฟ๐ง๐ง๐ง๐ง๐ง๐ง
๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง๐ง ๐งก๐งข๐งฃ๐งค๐งฅ๐งฆ๐งง๐งจ๐งฉ๐งช๐งซ๐งฌ๐งญ๐งฎ๐งฏ๐งฐ๐งฑ๐งฒ๐งณ๐งด๐งต๐งถ๐งท๐งธ๐งน๐งบ๐งป๐งผ๐งฝ๐งพ๐งฟ๐ฉฐ๐ฉฑ๐ฉฒ๐ฉณ๐ฉด๐ฉน๐ฉบ๐ฉป๐ฉผ๐ช๐ช๐ช๐ช๐ช๐ช
๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช๐ช ๐ชก๐ชข๐ชฃ๐ชค๐ชฅ๐ชฆ๐ชง๐ชจ๐ชฉ๐ชช๐ชซ๐ชฌ๐ชญ๐ชฎ๐ชฏ๐ชฑ๐ชด๐ชต๐ชถ๐ชท๐ชธ๐ชน๐ชบ๐ชป๐ชผ๐ชฝ๐ชฟ๐ซ๐ซ๐ซ๐ซ
๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ๐ซ ๐ซก๐ซฆ๐ซง๐ซฐ๐ซฑ๐ซฒ๐ซณ๐ซต๐ซถ๐ซทtxtThe challenge uses a custom emoji-based encoding scheme, inspired by Base64.
-
Convert to bits
Each character of the input message is converted to its ASCII value, then represented as an 8-bit binary string. -
Group into 10-bit chunks
The binary stream is padded with zeros until its length is divisible by 10.
Every 10-bit chunk is then interpreted as an integer. -
Map integer โ emoji
Each integer is used as an index into a large emoji table (emoji.txt).
Example:0000001010 (decimal 10)โ 10th emoji in the table. -
Padding with ๐
If the total length of encoded emojis is not a multiple of 4, extra ๐ characters are added (similar to=padding in Base64).
Decoding Process
- Remove ๐ padding.
- Convert each emoji back to its corresponding index.
- Convert the index into a 10-bit binary string.
- Concatenate all 10-bit chunks and split into 8-bit segments.
- Convert the 8-bit values back into ASCII characters.
Summary In short:
8-bit ASCII โ 10-bit chunks โ emoji table โ encoded string (with ๐ padding)
The reverse process recovers the original message.
Okay, hereโs my decode script.
#!/usr/bin/env python3
# decoder untuk chall.py
with open('emoji.txt', 'r', encoding='utf-8') as f:
emoji = list(f.read().strip())
table = {i: ch for i, ch in enumerate(emoji)}
rev_table = {ch: i for i, ch in enumerate(emoji)}
def decode(enc):
# buang padding ๐
enc = enc.rstrip("๐")
# ambil index dari tiap emoji
nums = [rev_table[ch] for ch in enc]
# convert ke biner 10-bit
bits = ''.join(f'{n:010b}' for n in nums)
# ambil per 8-bit
out = []
for i in range(0, len(bits), 8):
byte = bits[i:i+8]
if len(byte) < 8:
break
out.append(int(byte, 2))
return bytes(out).decode(errors="ignore")
if __name__ == "__main__":
from chall import encode
msg = "Hello!"
enc = encode(msg.encode())
dec = decode(enc)
print("enc:", enc)
print("dec:", dec)pythonfrom chall import encode # from chall.py
from decoder import decode # decoder that i've created
enc_data = "๐ช๐ฐ๐๐๐๐คต๐๐๐ท๐ฆจ๐ฅฉ๐๐ผ๐ฅ๐งท๐ฅณ๐๐๐
๐ถ๐ท๐๐คง๐ฃ๐๐ฅต๐๐ฆฝ๐๐ง๐ชฅ๐ฆฟ๐๐๐๐ง๐๐ญ๐ฅฌ๐ฒ๐ซ๐๐๐"
decoded = decode(enc_data)
print(decoded)pythonFlag:
fwectf{n0_r0ck37_3m0ji_n0_llm}sh๐ Reverese Engineering#
strings jacking#
Description
ๅๅฟ่ ๅใใฎใชใใผในใจใณใธใใขใชใณใฐ๏ผ้ ๅผตใฃใฆ๏ผ
Solve
I donโt know what was the description meaning, but from the challโs name, we know itโs about strings command on linux.
Just try to use this command, and i got the flag.
strings strings_jackingsh![ss gambar] Flag:
fwectf{5tr1n65_30F_p4ss937_0011}shNo need Logical Thinking#
Description
่ซ็็ๆ่ใฏใฉใใช็ฉไบใซใๅฟ ่ฆใ
Logical Thiniking is need for everything.
Solve
So, i got the challenge.pl which is written in perl language.
process_flag(FileName) :-
open(FileName, read, Stream),
read_string(Stream, _, Content),
close(Stream),
string_codes(Content, Codes),
transform_codes(Codes, 1, Transformed),
string_codes(NewString, Transformed),
writeln(NewString).
transform_codes([], _, []).
transform_codes([H|T], Index, [NewH|NewT]) :-
NewH is H + Index,
NextIndex is Index + 1,
transform_codes(T, NextIndex, NewT).
%EXECUTE
%?- process_flag('flag.txt').perlWhen opening the challenge, I saw a Prolog file Challenge.pl and an encrypted output output.txt.
The Prolog code defined a simple transformation: each character of the flag was converted to its ASCII code, then the index of that character (starting from 1) was added. In other words, the first character is shifted by +1, the second by +2, the third by +3, and so on.
![gambar ss cat .pl and output]
Naturally, to reverse this, I just need to subtract the index from each character instead of adding it. However, when I tried to decode output.txt, the result was messy, full of strange symbols like ยป, ยค, ยข. At first it looked like the algorithm was wrong, but after checking the raw hex with xxd, I realized the problem came from the way Prolog wrote the file. Characters above 0x7F were encoded as multi-byte UTF-8 sequences, which introduced extra 0xC2 bytes into the output.
The fix was simple: read the file as raw bytes and strip out the 0xC2 artifacts before applying the reverse transformation. Then, for each byte, subtract its index and rebuild the string.
with open("output.txt", "rb") as f:
data = f.read()
# Buang semua 0xC2 yang jadi artefak UTF-8
clean = data.replace(b'\xc2', b'')
result = []
for i, b in enumerate(clean, start=1):
result.append(chr((b - i) % 256))
flag = "".join(result)
print(flag)pythonWith this adjustment, the decrypted text gave me a clean flag in the expected format: Flag:
fwectf{the_Pr010g_10gica1_Languag3!}sh