<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Codegate2026 on k1nt4r0u's site</title><link>https://blog.238796234.xyz/categories/codegate2026/</link><description>Recent content in Codegate2026 on k1nt4r0u's site</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>Copyright (c) k1nt4r0u</copyright><lastBuildDate>Sun, 29 Mar 2026 21:54:48 +0700</lastBuildDate><atom:link href="https://blog.238796234.xyz/categories/codegate2026/index.xml" rel="self" type="application/rss+xml"/><item><title>Cobweb</title><link>https://blog.238796234.xyz/writeups/codegate2026/cobweb/writeup/</link><pubDate>Sun, 29 Mar 2026 21:54:48 +0700</pubDate><guid>https://blog.238796234.xyz/writeups/codegate2026/cobweb/writeup/</guid><description>&lt;h1 class="relative group"&gt;CODEGATE 2026 Quals - Cobweb
 &lt;div id="codegate-2026-quals---cobweb" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#codegate-2026-quals---cobweb" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Category: Web&lt;/li&gt;
&lt;li&gt;Challenge: &lt;code&gt;Cobweb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Description: &lt;code&gt;I wanted to create a web application.. but I don't know how to use web frameworks. So I decided to use pure C to make a web application!&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Solver: &lt;code&gt;exploit_admin_post_xss.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Transport helper: &lt;code&gt;solve.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;TL;DL
 &lt;div id="tldl" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#tldl" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The challenge looks like a stored-XSS task at first, but that is only half right. The actual entry point is a one-byte stack overwrite in &lt;code&gt;edit_post&lt;/code&gt;. If I make the escaped content length land exactly on &lt;code&gt;0x6000&lt;/code&gt;, the trailing NUL from &lt;code&gt;html_escape()&lt;/code&gt; zeros the low byte of the saved &lt;code&gt;user_id&lt;/code&gt; local. That pushes the request into the admin SQL branch, rewrites my post as &lt;code&gt;user_id = 0&lt;/code&gt;, and then the admin-only render path decodes the escaped content back into raw HTML. Only after that ownership flip does the stored script become real JavaScript in the bot&amp;rsquo;s browser.&lt;/p&gt;</description></item><item><title>Cogwartslang</title><link>https://blog.238796234.xyz/writeups/codegate2026/cogwartslang/writeup/</link><pubDate>Sun, 29 Mar 2026 21:54:48 +0700</pubDate><guid>https://blog.238796234.xyz/writeups/codegate2026/cogwartslang/writeup/</guid><description>&lt;h1 class="relative group"&gt;CODEGATE 2026 Quals - CogwartsLang
 &lt;div id="codegate-2026-quals---cogwartslang" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#codegate-2026-quals---cogwartslang" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Category: Reverse Engineering&lt;/li&gt;
&lt;li&gt;Challenge: &lt;code&gt;CogwartsLang&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Solver: &lt;code&gt;solve.grim&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;TL;DL
 &lt;div id="tldl" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#tldl" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The language syntax is mostly decoration. The real challenge is the oracle host module loaded by &lt;code&gt;harness&lt;/code&gt;. Once I understood that the important state lived in the host and not in the source language, the solve became a timing problem: reconstruct the oracle&amp;rsquo;s arithmetic, identify the exact checkpoint and ticket values, and call the host functions in the right order without accidentally burning extra ticks.&lt;/p&gt;</description></item><item><title>Comqtt</title><link>https://blog.238796234.xyz/writeups/codegate2026/comqtt/writeup/</link><pubDate>Sun, 29 Mar 2026 21:54:48 +0700</pubDate><guid>https://blog.238796234.xyz/writeups/codegate2026/comqtt/writeup/</guid><description>&lt;h1 class="relative group"&gt;CODEGATE 2026 Quals - comqtt
 &lt;div id="codegate-2026-quals---comqtt" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#codegate-2026-quals---comqtt" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Category: Pwn&lt;/li&gt;
&lt;li&gt;Challenge: &lt;code&gt;mqtt&lt;/code&gt; / &lt;code&gt;comqtt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Solver: &lt;code&gt;solve.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;TL;DL
 &lt;div id="tldl" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#tldl" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The broker has a retained-message deletion bug that leaves a stale tail entry behind after compaction. On the next retained insert, that stale slot frees a payload pointer that a live retained entry still references. Because each client runs in its own thread and glibc tcache is per-thread, that one mistake becomes a cross-thread tcache-dup primitive. I used it first to build an arbitrary-read oracle, then to dump the live libc image, resolve &lt;code&gt;system()&lt;/code&gt; from the in-memory ELF data, and finally overwrite &lt;code&gt;free@GOT&lt;/code&gt; with the real runtime address instead of guessing a libc version.&lt;/p&gt;</description></item><item><title>Greybox</title><link>https://blog.238796234.xyz/writeups/codegate2026/greybox/writeup/</link><pubDate>Sun, 29 Mar 2026 21:54:48 +0700</pubDate><guid>https://blog.238796234.xyz/writeups/codegate2026/greybox/writeup/</guid><description>&lt;h1 class="relative group"&gt;CODEGATE 2026 Quals - Greybox
 &lt;div id="codegate-2026-quals---greybox" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#codegate-2026-quals---greybox" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Category: Reverse Engineering&lt;/li&gt;
&lt;li&gt;Challenge: &lt;code&gt;Oh! My Greybox Keeps Running!&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Files: &lt;code&gt;deploy/prob&lt;/code&gt;, &lt;code&gt;deploy/target&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Solver: &lt;code&gt;solver.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;TL;DL
 &lt;div id="tldl" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#tldl" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The binary hides a small VM behind fake &lt;code&gt;FILE&lt;/code&gt; state and libc teardown machinery. The hard part is not the arithmetic. The hard part is recognizing that the weird runtime wrapper is only there to make the VM harder to spot. Once I aligned the handler table correctly and confirmed how the scheduler dispatches handlers, the shortest reliable solve was to record one concrete trace, replay that trace symbolically, and let &lt;code&gt;z3&lt;/code&gt; recover the 64-byte accepted input.&lt;/p&gt;</description></item><item><title>Oldschool</title><link>https://blog.238796234.xyz/writeups/codegate2026/oldschool/writeup/</link><pubDate>Sun, 29 Mar 2026 21:54:48 +0700</pubDate><guid>https://blog.238796234.xyz/writeups/codegate2026/oldschool/writeup/</guid><description>&lt;h1 class="relative group"&gt;CODEGATE 2026 Quals - oldschool
 &lt;div id="codegate-2026-quals---oldschool" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#codegate-2026-quals---oldschool" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Category: Reverse / AEG&lt;/li&gt;
&lt;li&gt;Challenge: &lt;code&gt;oldschool&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Description: &lt;code&gt;Back to the past&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Solver: &lt;code&gt;solver.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Client helper: &lt;code&gt;drive_client.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;TL;DL
 &lt;div id="tldl" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#tldl" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The provided Go client is only a courier. The real challenge is the ELF it downloads every round. Each round binary checks &lt;code&gt;sha256(input[:4])&lt;/code&gt;, uses those same four bytes to decrypt a 7-instruction VM program, runs the remaining 60 bytes through that VM, applies one more generated bytewise transform, and compares the result against a target buffer in &lt;code&gt;.rodata&lt;/code&gt;. I solved it by separating the stable part from the unstable part: recover the 4-byte prefix statically, invert the VM cleanly, and let one or two GDB probes reveal the final generated stage instead of trying to re-lift that tail by hand every round.&lt;/p&gt;</description></item><item><title>Tinyirc</title><link>https://blog.238796234.xyz/writeups/codegate2026/tinyirc/writeup/</link><pubDate>Sun, 29 Mar 2026 21:54:48 +0700</pubDate><guid>https://blog.238796234.xyz/writeups/codegate2026/tinyirc/writeup/</guid><description>&lt;h1 class="relative group"&gt;CODEGATE 2026 Quals - tinyIRC
 &lt;div id="codegate-2026-quals---tinyirc" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#codegate-2026-quals---tinyirc" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Category: Pwn&lt;/li&gt;
&lt;li&gt;Challenge: &lt;code&gt;tinyIRC&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remote launcher: &lt;code&gt;nc 15.165.70.236 20998&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Solver: &lt;code&gt;solve.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;TL;DL
 &lt;div id="tldl" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#tldl" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The wrapper port is not the IRC service. It prints the real port, keeps the wrapper process attached to the child, and becomes the side channel that later carries the leak and the flag. Inside the IRC server, &lt;code&gt;QUIT&lt;/code&gt; clears a client slot while the recv loop is still using the stale pointer, and a reused slot can come back with a negative &lt;code&gt;input_len&lt;/code&gt;. That negative length becomes a reusable cross-slot overwrite. I used it first to turn &lt;code&gt;memmove()&lt;/code&gt; into &lt;code&gt;printf()&lt;/code&gt; for a same-process libc leak, then to replace &lt;code&gt;strtok@got&lt;/code&gt; with &lt;code&gt;system()&lt;/code&gt; and run &lt;code&gt;cat /home/ctf/flag &amp;gt;&amp;amp;2&lt;/code&gt;.&lt;/p&gt;</description></item></channel></rss>