Hello Navi

Tech, Security & Personal Notes

I like to save my files as pdfs. Kashi kings hate 184.

Initial Analysis

The file is named flag.pdf, but standard PDF analysis tools fail to recognize it:

1
2
pdfid flag.pdf
# Output: Not a PDF document

Using the file command reveals its true identity:

1
2
file flag.pdf
# Output: flag.pdf: Netpbm image data, size = 284 x 150, rawbits, pixmap

The challenge hint "Kashi kings hate 184" suggests that the height of the image (currently 150) has been tampered with and should likely be 184.

Extraction & Decoding

Netpbm (PPM) files use a plain-text header. We can repair the height by editing the file header. Opening the file in a hex editor or a text editor like vim (using :set binary or simply editing the ASCII header) reveals:

1
2
3
4
P6
284 150
255
[Binary Data...]

Change the height value from 150 to 184:

1
2
3
4
P6
284 184
255
[Binary Data...]

After saving the change, the image can be opened with a standard image viewer to reveal the flag.

Flag

kashiCTF{iLOVEkashi}

Generating primes is expensive. I optimized my key generation to be twice as fast. The modulus is 4096 bits β€” perfectly secure.

Initial Analysis

The hint "optimized my key generation to be twice as fast" suggests that instead of generating two distinct large primes, the author might have reused the same prime (\(n = p^2\)) or chosen two primes that are extremely close to each other. This makes the modulus vulnerable to Fermat's Factorization Method or simply taking the square root.

Extraction & Decoding

Given a 4096-bit modulus \(n\), we can check if it's a perfect square or if its factors are close to \(\sqrt{n}\) by starting from \(\lfloor\sqrt{n}\rfloor\) and searching downwards. Once factored, we calculate \(\phi(n)\), derive the private key \(d\), and decrypt the AES key which was used to encrypt the flag.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import math
import base64
from Crypto.Util.number import long_to_bytes, bytes_to_long
from Crypto.Util.Padding import unpad
from Crypto.Cipher import AES

# Modulus and public exponent
n = 0x752a94a112ba0ce096f47934dac094d3d07b8c036613938142c0d4c15fc82692eee38d2457dd8d16472c4ddbe8cb5e2a6331e0ca0351094fc9516559768ebfe44509154d64116fa1fe1daf698413d37c9fe3406555f3190e29d99bee0cdd663d531c8e818f2686c7ad24338b4e93c6bfbd1b5a6dc5161316b2cb9ac1ae05a4ac43fdeb3b024b2e00dfcd87069ea1645996d9ad16ac3a9697414c17279112303a1d21136a99dc47628e15a3d6e18779de7aec310331dff1a81871b03e214de09f56c0f3de02f9f399be4ebc094f34b578d311a8b48e9c6cf2fa2f4e321f1dab0a99e5b9d99464c19452d9cc21544ac8e32fb9f13d1b2990758de0876de465cbd3632f846ef49fd7b97abee2ce529cfbc75a0d0792df6cc8091198134e9f646cf7d33c85c4ddd2c4b9a248c2c470d7369ebc7245bcec049455da2ceb742b26058514418398149d03cd1ad74a997375d0462a43e73aa62fc1f7e0dcc67e8f1559073074b9b8d3c37edfcfce67fd1822227933c5a14425d76119fc0a25da4c059761c86bc3077c4d096d9b9f6ae2faf728dbf24d48fa74d99c8c0d8780d2963ca9eccef0dd847ce22fc5b13793981257a9d4dd1af965e9baa5bd9fc4e3321cf8c6fd9871e342e5ae0dff19ab6e9fd8e14b5cc766b92df3306ef63af248b019528928644007c17e31918f9fdf10daeadc1eb8abeb6297bdc8f8e9b27c591f12159479
e = 65537

# Factor n
p = math.isqrt(n)
while n % p != 0:
p -= 1
q = n // p

# Calculate phi
if p == q:
phi = p * (p - 1)
else:
phi = (p - 1) * (q - 1)

# Decrypt AES Key
d = pow(e, -1, phi)
ct_b64 = "MVoAMG4KRlXdSxEtVL/GpwXWyelWmAsJJhMnPaTzF2Hhjm/h/vkHJKQIyHSld2XuB6Q0sWq/TN1dkSePEB1oq6ugzMcgp5VQ9Xn0mOCn1GZ7fP3bKUVD6mG1bt3dkHxzlAT7v6c6xKaTtJJKTV3JXnB2u3duW4dCrFyassEjHM1PEML3CWqJBrgxnlTIYI4i9ydwg1MF1fTOBTm2KLlQ6rIGnBWcGwg4k+8I7e0mIbhod53w3FzIPXePv0ONVp+HBn4XsICwEHhJLXixmHcEz0jxwCgRdz9qr+Ur1pOaVuKN/26cwpYdVTlY5Fk7KapoV3Ews69353gCa+QYiJtzuwr1uFTBe74GfZZ8xzxFK51TnMbqB1M5cpzBK8/TK+ES/+yy1R4jsGkQ4i7Qz0oAsqBoNExSaLsNgwzZe4dYRE2BwDy2tW2QAYFUeU+SVjUb2BI67QtQYl2g+GB0kAMzbcRFr/kykIHqqb2N05BxgRrtsFjq2zWvpJJ71OFCrWVg8IzO7N+WUXFFyFv7ZfdnKOhC/iPNNmLbJXa3Gul89Fa6VyvCJw6lA/t7QCsjtcVG7ox51JAvoHhw5FLIpT+wmfq969iUujkXzLpjyXBVrfnEdjRt61zGEd3tmWIYst721GcKnbxKBehxwpseDBYR0hJRy+CIf5SnrP6/Blq55cQ="
ct_int = bytes_to_long(base64.b64decode(ct_b64))
aes_key = long_to_bytes(pow(ct_int, d, n))

# Decrypt Flag
iv = base64.b64decode("XSCnpZLyN1Oin7F67hOKWQ==")
flag_ct = base64.b64decode("n+H1n3ezKEm0ulyLMcp/ShxLZAddKX7y848o/Lf/56qDev/DPBz+IRcJ14yHWGOuodMaMwyLZi9er7slNa+QMw==")

cipher = AES.new(aes_key, AES.MODE_CBC, iv)
flag = unpad(bytes(cipher.decrypt(flag_ct)), AES.block_size).decode()

print(f"\n[+] FLAG: {flag}")

Flag

kashiCTF{wh3n_0n3_pr1m3_1s_n0t_3n0ugh_p_squared_1s_w0rs3}

Wait, you forgot to give me the Advent calendar!?!?! And what is that supposed to mean, I should have opened the doors up until today?? Ugh, okay, then I'll start: Door 1

Investigation

The hint suggests that we need to visit the "doors" of the Advent calendar. The URL structure was identified as:

1
GET https://hack.arrrg.de/adventskalender/$$ HTTP/1.1

Where $$ represents the door number. To find the flag, we need to check all possible doors (1 to 30).

Solution

Using Zaproxy (OWASP ZAP) or a similar fuzzer, we can automate the process:

  1. Intercept/Send Request: Create a base request to https://hack.arrrg.de/adventskalender/1.
  2. Set Payload: In Zaproxy's fuzzer, set the payload for the door number position.
  3. Configure Generator: Use a Numberzz generator:
    • From: 1
    • To: 30
    • Step: 1
  4. Execute Fuzz: Start the fuzzer and monitor the responses.
  5. Analyze Results: Look for a response that differs in content.

After fuzzing, collecting the responses and looking for a secret message was revealed the hidden message.

THE ANSWER: FELIZNAVIDAD

A network analysis challenge where data was exfiltrated via DNS queries.

Challenge Description

A network capture was obtained from an internal monitoring system after suspicious activity was detected. The traffic appears mostly benign, but analysts believe data was covertly exfiltrated during normal communication.

Initial Reconnaissance

Checking the protocol distribution of the capture.pcap file using tshark:

1
tshark -r capture.pcap -q -z io,phs

The output confirms that 100% of the traffic is DNS, indicating that DNS is being used as a tunnel for exfiltration.

DNS Query Analysis

Extracting the DNS query names reveals two distinct patterns: 1. Repetitive queries for common domains like kashi.com and amazon.com (likely noise). 2. High-entropy subdomains under .exfil.internal.

Extracting the subdomains:

1
2
3
4
5
6
7
tshark -r capture.pcap -T fields -e dns.qry.name | grep ".exfil.internal"
# Example output:
# NNQXG2DJINKE.exfil.internal
# M63ENZZV6ZLY.exfil.internal
# MZUWY5DSMF2G.exfil.internal
# S33OL5UXGX3T.exfil.internal
# NZSWC23ZPU.exfil.internal

Data Recovery

The strings (e.g., NNQXG...) are characteristic of Base32 encoding. We can concatenate these strings and decode them to recover the secret payload:

1
2
3
4
5
6
7
8
import base64

# Concatenated subdomains
encoded_payload = "NNQXG2DJINKEM63ENZZV6ZLYMZUWY5DSMF2GS33OL5UXGX3TNZSWC23ZPU"

# Base32 decoding (adding padding if necessary)
decoded = base64.b32decode(encoded_payload + "======").decode()
print(f"Decoded flag: {decoded}")

Flag

kashiCTF{dns_exfiltration_is_sneaky}

A forensics challenge involving network traffic analysis and IP Time-to-Live (TTL) steganography.

Challenge Description

A packet capture was collected from an internal network segment during routine monitoring. No alerts were triggered at the time, and the traffic appears largely normal. Your task is to analyze the capture and determine whether any meaningful information can be recovered.

Initial Analysis

The provided file ttl_stego.pcap contains a series of ICMP Echo (ping) requests. While the payloads appear standard, the IP Time-to-Live (TTL) values fluctuate between 64 and 65, suggesting binary data is encoded in these variations.

Using tshark to inspect the TTL values:

1
2
tshark -r ttl_stego.pcap -c 10 -T fields -e ip.ttl
# Output: 64, 65, 65, 64, 65, 64, 65, 65, 64, 65...

Extraction & Decoding

The TTL values can be mapped to binary bits: - 64 \(\rightarrow\) 0 - 65 \(\rightarrow\) 1

We can extract the full sequence of TTLs and decode them using a Python script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import sys

# Extract TTLs using: tshark -r ttl_stego.pcap -T fields -e ip.ttl > ttls.txt
with open('ttls.txt', 'r') as f:
ttls = [int(line.strip()) for line in f if line.strip()]

# Convert TTLs to bits
bits = "".join(['0' if t == 64 else '1' for t in ttls])

# Convert bits to characters (8 bits per byte)
flag = ""
for i in range(0, len(bits), 8):
byte = bits[i:i+8]
if len(byte) == 8:
flag += chr(int(byte, 2))

print(f"Decoded message: {flag}")

Flag

kashiCTF{ttl_stego_is_evil}

I like to have my poems saved on CTFd instances like this. But the admin does like it, so I hid the secret in my poem.

Solution

The provided poem contains a significant amount of trailing tabs and spaces at the end of each line. This is a classic indication of SNOW (Steganographic Nature Of Whitespace) steganography.

By using a SNOW decoder (such as the web-based snow.js decoder), we can extract the hidden message from the poem text:

1
2
3
4
5
6
7
8
9
10
11
12
13
The way a crow	      	  	   	   		     	   	      
Shook down on me
The dust of snow
From a hemlock tree

Has given my heart
A change of mood
And saved some part
Of a day I had rued.




The decoded message reveals the flag.

Flag

kashiCTF{1_like_poems_but_1_lik3_u_more<3}

Its Time to be sane. I wish I could give the flag, but I can't. Try searching this site. xd :>

Solution

The flag was split into two parts found in different locations on the platform:

  1. robots.txt: Navigating to https://kashictf.iitbhucybersec.in/robots.txt revealed the first part of the flag:

    1
    2
    3
    User-agent: *
    Disallow: /admin
    kashiCTF{50_you_did

  2. Home Page Source: Inspecting the HTML source code of the main landing page https://kashictf.iitbhucybersec.in/ revealed the second part hidden inside a comment:

    1
    <!--- _endup_ge77ing_the_flag_hehe} --->

Combining both parts yields the full flag.

Flag

kashiCTF{50_you_did_endup_ge77ing_the_flag_hehe}

The flag was hidden in the #rules channel of the kashiCTF Discord server.

Solution

The following encoded string was found:

1
Tk5RWEcyREpJTktFTTYzVU5CVVhHWDNYTUZaVjYzVFBPUlBXUVlMU01SNlFVPT09Cg==
  1. Base64 Decoding: Decoding the string once results in a Base32-encoded string.
    1
    NNQXG2DJINKEM63UNBUXGX3XMFZV63TPORPWQYLSMR6QU===
  2. Base32 Decoding: Decoding the resulting string

Flag

kashiCTF{this_was_not_hard}

Unless otherwise noted, all flags match the regular expression RS{[?:]*} (letters, digits, !, ?, :, and _ are allowed).

Welcome to RITSEC CTF

Initial Analysis

The "Welcome" challenge typically points to where the rules or information about the CTF can be found.

Solution

The flag can be found at the end of the information page: https://ctfd.ritsec.club/info.

Flag

RS{why_1s_th3_rum_g0n3?}