<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Reverse Engineering on Monish Kumar&#39;s Blog</title>
        <link>https://itsmonish.pages.dev/tags/reverse-engineering/</link>
        <description>Recent content in Reverse Engineering on Monish Kumar&#39;s Blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Fri, 20 Mar 2026 10:41:25 +0530</lastBuildDate><atom:link href="https://itsmonish.pages.dev/tags/reverse-engineering/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>JITFP - PicoCTF 2026 Challenge Writeup</title>
        <link>https://itsmonish.pages.dev/blog/jitfp-picoctf-2026/</link>
        <pubDate>Fri, 20 Mar 2026 10:41:25 +0530</pubDate>
        
        <guid>https://itsmonish.pages.dev/blog/jitfp-picoctf-2026/</guid>
        <description>&lt;p&gt;I took part in PicoCTF 2026, that happened between 9th March 2026 to 19th March 2026. I ranked at 570 globally and got a total score of 11,000 out of the maximum 14,500.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/1.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;picoctf2026-result&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t plan on writing writeups for this one. But there was one challenge that was so good, that I had to write about it.&lt;/p&gt;
&lt;h1 id=&#34;jitfp&#34;&gt;JITFP
&lt;/h1&gt;&lt;h2 id=&#34;challenge-description&#34;&gt;Challenge Description
&lt;/h2&gt;&lt;p&gt;If we can crack the password checker on this remote host, we will be able to infiltrate deeper into this criminal organization. The catch is it only functions properly on the host on which we found it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/2.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;challenge-description&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;The challenge is now moved to picoCTF gym, you can access it &lt;a class=&#34;link&#34; href=&#34;https://play.picoctf.org/practice/challenge/737?category=3&amp;amp;page=1&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;. In the live CTF, this challenge was for 500 points, which was the highest among all the other challenges (except for other 500 point challenge, of course).&lt;/p&gt;
&lt;h2 id=&#34;solution&#34;&gt;Solution
&lt;/h2&gt;&lt;p&gt;The description doesn&amp;rsquo;t tell us much or doesn&amp;rsquo;t give us any files to actually reverse engineer binaries. However, there is an instance associated with the challenge. Launching it gives you credentials for a SSH login on a remote host.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/3.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;logging-in&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Logging in, we are greeted with, uh well, a message. And put in a directory with only one binary. Assuming this is the target binary, I started to poke it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/4.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;first-runs&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;The binary takes an arguement input and does something with it. There is a loading bar like output that takes some time to complete before printing the incorrect message. I wanted to time it, so I used &lt;code&gt;time&lt;/code&gt; utility. It takes around 33 seconds to run once. This brings a thought, is this a timing side channel attack scenario? Perhaps if I give a correct character at a position it would speed up or slow down? I tried it but it still ran the same 33 seconds.&lt;/p&gt;
&lt;p&gt;So to move further, we have to pop open and look under the hood. Since the binary was in a SSH instance, I used &lt;code&gt;scp&lt;/code&gt; to make a local copy and then used it to analyze it locally. I loaded it in Binary Ninja and the main function looked like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/5.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;binja-main&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;We have a peculiar looking if statement, where if the condition is false, it calls another function, prints out &amp;ldquo;Incorrect&amp;rdquo; and then exits. The other flow is what we should be doing to get the correct message. We still need to know what the function &lt;code&gt;sub_401932&lt;/code&gt; does.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/6.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;sub-function&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;So basically, it prints out asterisk, sleeps and prints a new line and exits. Not that interesting except this is where the sleep happens.&lt;/p&gt;
&lt;p&gt;Going back to the if condition, it didn&amp;rsquo;t make much sense to me, so I decided to get a second opinion from IDA (yes I have multiple decompilers, they are all awesome in their own way).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/7.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;ida-main&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Now that is better. So we have one memory array that index into another memory array which has function pointers because whatever is in there is used to call a function, so the most sensible conclusion is that they are function pointers. So let&amp;rsquo;s take a look at the memory arrays. At the first layer memory array, that index into the function pointer array we have:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/8.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;4020-array&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;So we have a bunch of indices indeed. Looking at the second array, the one which should have function pointers, we have:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/9.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;4120-array-ida&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;That don&amp;rsquo;t look like much. So I took a look at the same address in Binary Ninja:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/10.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;4120-array-binja&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;There is nothing here. So I started to look around for other things.&lt;/p&gt;
&lt;p&gt;Another important detail I found was that in the binary there are a lot of functions like these:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/11.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;check-funcs&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;There were functions like these for all the lowercase and uppercase alphabets, digits, underscore and curly braces. So these functions basically check if the given character is the one there are validating or not. So it is logical to assume that, these are the functions that would be present and called from the function pointer array.&lt;/p&gt;
&lt;p&gt;However that is empty. Or is it just uninitialized? Perhaps the function pointers are populated at runtime only? And then the title suddenly made sense, &amp;ldquo;Just In Time Function Pointers&amp;rdquo;, JITFP. So I just have to dump whatever that memory is in runtime and get the functions pointers. Easy, right?. Or that&amp;rsquo;s what I thought. But no, I can&amp;rsquo;t even run the thing in my local machine&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/12.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;failed-local-run&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Now, this shouldn&amp;rsquo;t really come as a surprise, because the description of challenge literally tells that we can only run it on the remote machine. So I have to rely on any debugging tools on the remote machine.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/13.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;no-tools-on-remote&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;So, in terms of tools, there was none. Hence, the question became &amp;ldquo;how can I dump a memory of a live running process?&amp;rdquo;. Yes, the procfs at &lt;code&gt;/proc&lt;/code&gt;. Every process&amp;rsquo;s has it&amp;rsquo;s mapping of memory at &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/maps&lt;/code&gt; and actual memory contents at &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/mem&lt;/code&gt;. So I opened two SSH shells into the remote machine with tmux and saw if I could access the procfs.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/14.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;procfs-map&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;I could. Now we just have to dump the memory contents into a file and analyze it. Turns out the file system is read-only. Great. So I thought of redirecting the memory to &lt;code&gt;xxd&lt;/code&gt; utility, copying the hex dump and then analyzing it. But before I could go further I wanted to check what kind of protection this binary has. Thankfully, &lt;code&gt;checksec&lt;/code&gt; was installed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/15.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;checksec-output&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;We got PIE, Position Independent Executable. But this shouldn&amp;rsquo;t really be a problem as PIE just randomizes the base address of the virtual memory. If we had ASLR, then it would have been hell, because the entire layout of the virtual memory would be randomized, but thankfully no.&lt;/p&gt;
&lt;p&gt;Now all I had to do was put together a bunch of commands that would take the &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/maps&lt;/code&gt; as input and dump the required memory. Since the memory we are interested is in &lt;code&gt;0x4120&lt;/code&gt;, the content would be present at base + &lt;code&gt;0x4120&lt;/code&gt;. We only need to read 264 bytes of information because that&amp;rsquo;s how long the function pointer array was. Put these together, I had this script to dump stuff:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./ad7e550b aaaa &amp;amp; pid&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$!;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;base&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;cat /proc/$pid/maps | grep -m1 &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;r--p 00000000&amp;#34;&lt;/span&gt; | cut -d&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;-&amp;#39;&lt;/span&gt; -f1&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;target&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;printf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%d&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;$((&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;16#&lt;/span&gt;$base &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;x4120&lt;span style=&#34;color:#66d9ef&#34;&gt;)))&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dd &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/proc/$pid/mem iflag&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;skip_bytes,count_bytes skip&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$target count&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;264&lt;/span&gt; 2&amp;gt;/dev/null | xxd -p;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gave an output like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/16.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;memory-dump&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;If I dumped the memory immediately, it is still uninititialized. So I had to add some sleep command to get some actual output. Right now it doesn&amp;rsquo;t look like much, but these do actually look like function pointers from a binary. I put together a small python script to parse this and print me the function offsets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;lt;dumped hex&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ptrs &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [int&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;from_bytes(data[i : i &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;], &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;little&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, len(data), &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;base &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;x&lt;span style=&#34;color:#f92672&#34;&gt;....&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;offsets &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [p &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; base &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; p &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; ptrs]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i, o &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; enumerate(offsets):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;idx &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;i&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;: offset 0x&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;o&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;x&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This prints out the offsets that are given by the addresses in the hexdump.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/17.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;function-offsets&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;And good enough, these offsets correspond to actual function offsets in the binary. So the only thing now to do is index this offsets using the first memory array and see in which order, which functions are being called. I extended the previous script a little to get that part done.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;lt;dumped hex&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;func_map &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;} &lt;span style=&#34;color:#75715e&#34;&gt;# A dictionary mapping which function offset correspond to which character&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dword_4020 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;] &lt;span style=&#34;color:#75715e&#34;&gt;# The indices from the first memory array&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ptrs &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [int&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;from_bytes(data[i : i &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;], &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;little&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, len(data), &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;base &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;x&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;offsets &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [p &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; base &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; p &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; ptrs]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;flag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; idx &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; dword_4020:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    flag&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(func_map[offsets[idx]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;join(flag))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Executing this gave:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/18.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;wrong-output-1&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Now that does not look like a flag to me. I checked my scripts and other things, everything seemed to be right. So I decided to do the same process one more time. And it gave me:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/19.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;wrong-output-2&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;An entirely different output. But why? I did everything the same, except for one thing. I adjusted the sleep duration in bash from 5 to 2, thinking I need to read the memory early. At this point I had no idea what to do and I almost gave up. It wasn&amp;rsquo;t until later it struck me, &amp;ldquo;&lt;strong&gt;what if the entirety of the function pointer array changes every second?&lt;/strong&gt;&amp;rdquo;. That would mean that only one memory address at a point of time would be the right one, the rest are just fillers.&lt;/p&gt;
&lt;p&gt;I modified the bash script I used to extract the memory from &lt;code&gt;procfs&lt;/code&gt; as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./ad7e550b aaaa &amp;amp; pid&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$!; i&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;1; cat /proc/$pid/maps; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; $i -lt &lt;span style=&#34;color:#ae81ff&#34;&gt;35&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  base&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;cat /proc/$pid/maps | grep -m1 &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;r--p 00000000&amp;#34;&lt;/span&gt; | cut -d&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;-&amp;#39;&lt;/span&gt; -f1&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  target&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;printf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%d&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;$((&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;16#&lt;/span&gt;$base &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;x4120&lt;span style=&#34;color:#66d9ef&#34;&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  dd &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/proc/$pid/mem iflag&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;skip_bytes,count_bytes skip&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$target count&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;264&lt;/span&gt; 2&amp;gt;/dev/null | xxd -p
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  i&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$((&lt;/span&gt;$i&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sleep &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This dumped the memory address 33 times. I put 35 just to be sure, in case. So I put all those hex dumps in a text file and modified my python script to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;func_map &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;} &lt;span style=&#34;color:#75715e&#34;&gt;# A dictionary mapping which function offset correspond to which character&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dword_4020 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;] &lt;span style=&#34;color:#75715e&#34;&gt;# The indices from the first memory array&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;parse_dump&lt;/span&gt;(line):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    hex_str &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; line&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;strip()&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;replace(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; bytes&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;fromhex(hex_str)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; [int&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;from_bytes(data[i : i &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;], &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;little&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, len(data), &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lines &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; open(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dumps.txt&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; f:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; _ &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(&lt;span style=&#34;color:#ae81ff&#34;&gt;33&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        l &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; _ &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(&lt;span style=&#34;color:#ae81ff&#34;&gt;9&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            l&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(f&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;readline()&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;strip(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        lines&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;join(l))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;base &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;x&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;flag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; second, line &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; enumerate(lines):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; second &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; len(dword_4020):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ptrs &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; parse_dump(line)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    idx &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; dword_4020[second]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ptr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ptrs[idx]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    offset &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ptr &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; base
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    char &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; func_map&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get(offset, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    flag&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(char)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;second &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;second&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;02d&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;: idx=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;idx&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#x&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; offset=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;offset&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;#x&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; char=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;char&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Flag: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;join(flag)&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, there is a bit of a timing requirement to this challenge, as the first time I ran it, it was some random output. But when I ran it again, it worked. I got:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/jitfp/20.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;the-flag&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;I still didn&amp;rsquo;t get the &amp;lsquo;p&amp;rsquo; in &amp;lsquo;picoCTF&amp;rsquo; for some reason, but I could fill it, submit it and get the points. This was such a cool challenge, that I had to rethink everything again and again and again. And the part where the function pointer array getting randomized for every second execpt for the right index was absolutely devious. Loved it.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Reverse Engineering - GoCrackMe1</title>
        <link>https://itsmonish.pages.dev/blog/huntress-ctf-2024/re-gocrackme1/</link>
        <pubDate>Sat, 26 Apr 2025 17:51:33 +0530</pubDate>
        
        <guid>https://itsmonish.pages.dev/blog/huntress-ctf-2024/re-gocrackme1/</guid>
        <description>&lt;h1 id=&#34;gocrackme1&#34;&gt;GoCrackMe1
&lt;/h1&gt;&lt;h2 id=&#34;challenge-statement&#34;&gt;Challenge Statement
&lt;/h2&gt;&lt;p&gt;Author: @HuskyHacks&lt;/p&gt;
&lt;p&gt;TENNNNNN-HUT!&lt;/p&gt;
&lt;p&gt;Welcome to the Go Dojo, gophers in training!&lt;/p&gt;
&lt;p&gt;Go malware is on the rise. So we need you to sharpen up those Go reverse engineering skills. We&amp;rsquo;ve written three simple CrackMe programs in Go to turn you into Go-binary reverse engineering ninjas!&lt;/p&gt;
&lt;p&gt;First up is the easiest of the three. Go get em!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Archive password: &lt;code&gt;infected&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Attachment: &lt;a class=&#34;link&#34; href=&#34;https://itsmonish.pages.dev/others/huntressctf-2024/gocrackme1/GoCrackMe1.zip&#34; &gt;GoCrackMe1.zip&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;solution&#34;&gt;Solution
&lt;/h2&gt;&lt;p&gt;Extracting the archive we are provided with ELF executable (linux executable) that is obviously written and compiled with Go language.&lt;/p&gt;
&lt;p&gt;Even though this is a reverse engineering challenge, my first thought was to run it. So when I ran it (of course in a virtual machine), I got an &amp;ldquo;Access denied!&amp;rdquo; straight. So there is a good chance there is a conditional statement in the binary, that controls the execution flow.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/gocrackme1/1.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;access denied&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;So I decided to do a static analysis and opened the file in &lt;a class=&#34;link&#34; href=&#34;https://github.com/rizinorg/cutter&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Cutter&lt;/a&gt; which is a nice frontend for the &lt;a class=&#34;link&#34; href=&#34;https://github.com/radareorg/radare2&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;radare2&lt;/a&gt; tool. Opening it, there was a lot of functions inside that turned up in the analysis. But Go language like most language, starts it execution from main function, I decided to look for the main function.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/gocrackme1/2.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;main function&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;At first I was focused on the hex data that was being declared and initialized. On a quick look they might seem like data put in different variables across different locations. But you see, they are being written to consecutive locations right after one another. The reason why they are broken is because they are moved to the memory in different instructions. Some decompilers may recognize this and collate them, but the one I used didn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;But then I looked below it, and saw a if-else statement. Since I already suspected a conditional statement somewhere that controls the flow, I thought this might be it. Both the if and else block contained a fprintln function which is basically print function in Go. Whatever the case might be, if this indeed is the check I&amp;rsquo;m looking for then reversing the jump statement that directs the execution flow should execute the other part.&lt;/p&gt;
&lt;p&gt;Cutter allows one to patch binaries if opened in write mode. So I made a copy of the binary as a backup if it is not what I think it is and switch to write mode. In Cutter any changes made to the binary in write mode is instantly written to the binary which is in contrast to several other tools which requires some sort of explicit &amp;lsquo;Patch binary&amp;rsquo; options to write to binary.&lt;/p&gt;
&lt;p&gt;So now, I&amp;rsquo;m looking for a jump statement in the disassembly.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/gocrackme1/3.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;disassembly&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;As I skimmed through the disassembly, the disassembler could locate the call that goes to the function &lt;code&gt;checkCondition&lt;/code&gt;. Following it is a &lt;code&gt;test&lt;/code&gt; instruction and a &lt;code&gt;je&lt;/code&gt; (jump if equal) condition. So basically this &lt;code&gt;je&lt;/code&gt; instruction is what I&amp;rsquo;m looking for.&lt;/p&gt;
&lt;p&gt;Cutter provides option to edit the instruction in such a way to reverse the jump, that is change &lt;code&gt;je&lt;/code&gt; to &lt;code&gt;jne&lt;/code&gt;. This turns the execution around.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/gocrackme1/4.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;reversing jump&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Now that I&amp;rsquo;ve reversed the jump now, all I have to do to test my theory is to run it. Which indeed provides the flag.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/gocrackme1/5.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;flag&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Even though I got the flag, I still wanted to check if the data I was focused on previously was indeed the data that was xored to give the flag. So I opened cyberchef, copied the data in it and put the key. You may find the key at the other end of the expression in the for loop which is &lt;code&gt;0x56&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/gocrackme1/6.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;another flag&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;And it indeed was that data. So this could be considered an alternate method to do the challenge.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Reverse Engineering - Stack It</title>
        <link>https://itsmonish.pages.dev/blog/huntress-ctf-2024/re-stack-it/</link>
        <pubDate>Sat, 26 Apr 2025 17:51:33 +0530</pubDate>
        
        <guid>https://itsmonish.pages.dev/blog/huntress-ctf-2024/re-stack-it/</guid>
        <description>&lt;h1 id=&#34;stack-it&#34;&gt;Stack It
&lt;/h1&gt;&lt;h2 id=&#34;challenge-statement&#34;&gt;Challenge Statement
&lt;/h2&gt;&lt;p&gt;Author: @sudo_Rem&lt;/p&gt;
&lt;p&gt;Our team of security analysts recently worked through a peculiar Lumma sample.&lt;/p&gt;
&lt;p&gt;The dentists helping us advised we floss at least twice a day to help out.&lt;/p&gt;
&lt;p&gt;He also gave us this weird file. Maybe you can help us out.&lt;/p&gt;
&lt;p&gt;Attachment: &lt;a class=&#34;link&#34; href=&#34;https://itsmonish.pages.dev/others/huntressctf-2024/stack-it/stack_it.bin&#34; &gt;stack_it.bin&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This challenge was accompanied with a per-user instance&lt;/p&gt;
&lt;h2 id=&#34;solution&#34;&gt;Solution
&lt;/h2&gt;&lt;p&gt;Running file command on the attachment, we can see that it&amp;rsquo;s an ELF executable.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/stack-it/1.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;file command&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Since this is a Reverse Engineering challenge I decided look into the disassembly. I used &lt;a class=&#34;link&#34; href=&#34;https://github.com/rizinorg/cutter&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Cutter&lt;/a&gt; with Ghidra decompiler plugin to disassemble and decompile the ELF binary for me.&lt;/p&gt;
&lt;p&gt;Luckily there was only one function in the ELF executable and it was fairly easy to understand. Let me walk you through it. Below is the screenshot of the decompiled function:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/stack-it/2.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;decompiled function&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;First thing we can notice is some data is written directly to the memory addresses &lt;code&gt;0x0804a050&lt;/code&gt; till &lt;code&gt;0x0804a054&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/stack-it/3.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;data decoded&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;And if you look at the data it is writing, this is hexadecimal for the characters f, l, a, g and {. Seems familiar huh?&lt;/p&gt;
&lt;p&gt;Next up we can notice variables &lt;code&gt;puVar7&lt;/code&gt; and &lt;code&gt;puVar8&lt;/code&gt; (names given by the decompiler), are initialized to some strings each.  It doesn&amp;rsquo;t matter much right now, but it will in a moment.&lt;/p&gt;
&lt;p&gt;We can also see another variable, a pointer to be specific, is made to point the address &lt;code&gt;0x0804a055&lt;/code&gt;. This is right after where the program wrote the &amp;lsquo;{&amp;rsquo; character above.&lt;/p&gt;
&lt;p&gt;Then there is a loop where the contents from &lt;code&gt;puVar7&lt;/code&gt; and &lt;code&gt;puVar8&lt;/code&gt; are XORed and put in the address of &lt;code&gt;puVar4&lt;/code&gt; incrementally, which is just a temporary pointer with same address as &lt;code&gt;puVar2&lt;/code&gt;, the original pointer.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/stack-it/4.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;post write&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Once the loop is over,  couple bytes of data is put at the end of it. It is &lt;code&gt;0x7d&lt;/code&gt; which is the &amp;lsquo;}&amp;rsquo; character and the 0 is essentially the null terminator. So this is our flag. But if you follow along the code, you&amp;rsquo;ll notice data is written again starting from &lt;code&gt;0x0804a050&lt;/code&gt; which is the start of the flag.&lt;/p&gt;
&lt;p&gt;So essentially, our flag is written to the memory, actually in the stack as it is a local variable, and then rewritten again. So to acquire the flag, we have to stop the execution midway and read the memory directly.&lt;/p&gt;
&lt;p&gt;We can use a debugger, a program that can stop execution of a running program and analyze it from various perspectives. It was originally intended for programmers to debug programs, but the print (or cout) statement method is widely used (so do I). So mostly it is used for reverse engineering and malware analysis.&lt;/p&gt;
&lt;p&gt;Anyway I went with using the GNU debugger (gdb) to get the job done. Oh and yeah, we are about the execute an unknown binary in a control manner, but still executing it. So it is advisable to do this in a virtual environment so that your main system is not affected. Checkout my &lt;a class=&#34;link&#34; href=&#34;https://github.com/ItsMonish/archvm-script&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;hacky script&lt;/a&gt; to quickly setup a arch linux vm.&lt;/p&gt;
&lt;p&gt;On loading the program with gdb, we can see that there is no symbols loaded required for &amp;ldquo;debugging&amp;rdquo;. Simply put we cannot disassemble the code directly.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/stack-it/5.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;no debugging symbols&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;But we already have the address actually. Cutter already disassembled the code and the assembly code is under the disassembly section.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/stack-it/6.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;disassembly&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;So we need address of the instruction right after the insertion of &amp;lsquo;}&amp;rsquo; character into the address space. So that address seems to be &lt;code&gt;0x8049045&lt;/code&gt;. So all I have to do is set a breakpoint at that address and examine the address space at &lt;code&gt;0x0804a050&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://itsmonish.pages.dev/images/huntressctf-2024/stack-it/7.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;execution and flag&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Set up a breakpoint at &lt;code&gt;0x08049048&lt;/code&gt; using command &lt;code&gt;break *0x08049048&lt;/code&gt;, then run the program to hit the breakpoint. Examined the address &lt;code&gt;0x0804a050&lt;/code&gt; with &lt;code&gt;x/30s 0x0804a050&lt;/code&gt; ( x - examine, 30 - 30 spaces, s - string format ). Why 30 strings? Not sure why but I do it like that. So yup, there&amp;rsquo;s the flag.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
