Post

ShaktiCTF 2025 Write-up

Full write-up of completed challenges in ShaktiCTF 2025 by AppleTree, covering Misc, OSINT, Rev, and Web categories.

ShaktiCTF 2025 Write-up

ShaktiCTF 2025 Write-up

Author: AppleTree
Team: APISec Avengers
Event Date: July 25–26, 2025
Platform: ShaktiCTF 2025
Flag Format: shaktictf{...}


✅ Completed Challenges Overview

Challenge NameCategoryPointsStatusDifficulty
Welcome FlagMisc100Beginner
water water everywhereMisc100Unrated
gooGOOgaaGAARev100Unrated
OpenSesameRev100Unrated
HoomanWeb100Unrated
Brain GamesWeb100Unrated

Total Personal Score: 600 points
Total Team Score: 1100 points
Final Rank: 127th of 554 total teams


Welcome Flag

Category: Misc
Points: 100
Difficulty: Beginner
Flag: shaktictf{c0ngratulations_y0u_h4ve_f0und_it!!!}

Description

The challenge served as an onboarding exercise to familiarize participants with the event Discord server.

Steps Taken

  • Joined the event Discord server
  • Checked channel names, pinned messages, announcements
  • Found organizer message in #announcements with text hidden in pipe blocks
  • Copying message to a plaintext editor revealed the flag

water water everywhere

Category: Misc (tagged OSINT)
Points: 100
Difficulty: Unrated
Flag: shaktiCTF{vellayani_lake}

Description

˚⊱🪷⊰˚

  • Replace all spaces with underscore
  • no caps inside shaktiCTF{random_lake}

Author: ._switch_

Steps Taken

  • Observed palm trees, lotus pads, tropical climate
  • Hypothesized Kerala or southern India
  • Searched Google Images for "kerala lake with lotus"
  • Matched to Vellayani Lake, Kerala
  • Verified via Google Maps and travel photography

gooGOOgaaGAA

Category: Rev
Points: 100
Difficulty: Unrated
Flag: shaktictf{b4byR3v_1s_cut3}

Description

Solve this babyrev challenge first ^-^

Steps Taken

  • Observed gaga() XOR function (renamed for manual analysis) with key "IWANTMOMOS"
  • Re-applied XOR to encrypted list to recover flag
1
2
3
4
5
6
7
def gaga_decrypt(encrypted, key):
    return ''.join(chr(ord(encrypted[i]) ^ ord(key[i % len(key)])) for i in range(len(encrypted)))

key = "IWANTMOMOS"
encrypted = [':','?',' ','%',' ','$',',','9',')','(','+','c','#','7','\x06','~','9','\x12','~',' ','\x16','4','4',':','g','0']
flag = gaga_decrypt(encrypted, key)
print(flag)  

OpenSesame

Category: Rev
Points: 100
Difficulty: Unrated
Flag: shaktictf{Hii1i1i1ii_^_^__3243242_3nj0y_r3v_^_}

Description

You discover the secret treasure in a thieves’ den, what might the magic password be?

-y0urk4rma

Steps Taken

  • Decompiled in Ghidra
  • Reversed rotations and XOR sequences seeded by fixed constants
  • Reconstructed ASCII characters from processed integers

Hooman

Category: Web
Points: 100
Difficulty: Unrated
Flag: shaktictf{n0on3_l1k3s_5ar4h}

Description

Try your best to prove being a Hooman!

Author: ._switch_

Steps Taken

  1. Review the Source Code

    We are given the Flask app source code app.py. Key behaviors:

    • On /login, a JWT is generated with are_you_hooman: False
    • The JWT is signed with HS256 and the secret 'Youcanneverhavethis'
    • The /hooman route only allows access if are_you_hooman: True
    • When decoding the JWT: ```python decoded = jwt.decode(token, key=None, options={“verify_signature”: False})
  2. Forge a JWT We can now forge a JWT without knowing the real secret. There are two approaches:

    Use jwt.io directly

    Use Python’s jwt.encode (PyJWT) — though some environments block HS256 without a key.

    To make it easy, I used jwt.io via archive.org, since newer versions of the tool enforce recommended requirements.

  3. Set the Cookie Once we get the JWT token from jwt.io, we set it in our browser’s cookies.

    In DevTools (Chrome or Edge):

    1. Go to Application > Cookies
    2. Find the domain
    3. Set a cookie named token to the forged JWT
  4. Reload the page.


Brain Games

Category: Web
Points: 100
Difficulty: Unrated
Flag: shaktictf{n0on3_l1k3s_5ar4h}

Description

🎮🧑‍💻

Author: ._switch_

Steps Taken

  • Inputs like help returned MD5 hash → confirmed command injection (though intended?)
  • Spaces, /, cat, ls blocked;
  • ;, dir allowed
  • Enumerated environment and listed files using:
    1
    
    dir;
    
  • Used ${IFS} to bypass space filter
  • Found partial flag in user.txt; hint pointed to /usr/local/flag
    1
    
    head${IFS}user.txt
    
  • Used ${HOME:0:1} to bypass / filter
  • Read final part of flag:
    1
    
    head${IFS}${HOME:0:1}usr${HOME:0:1}local${HOME:0:1}flag;
    
  • Combined flag parts for final flag

Takeaways

  • Misc & OSINT: Geolocation from visual cues and hidden messages in Discord are common quick wins
  • Reversing: Simple XOR and layered rotation/XOR patterns remain CTF staples
  • Web: JWT signature bypass and blacklist command injection are classic but valuable vulnerabilities to understand

Note: AI-assisted editing was used only for grammar, formatting, and consistency. All opinions are my own based on official OffSec documentation.

This post is licensed under CC BY 4.0 by the author.