<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Dillon Korman]]></title><description><![CDATA[Notes on computers and technology]]></description><link>https://dillonkorman.com/</link><image><url>https://dillonkorman.com/favicon.png</url><title>Dillon Korman</title><link>https://dillonkorman.com/</link></image><generator>Ghost 5.49</generator><lastBuildDate>Wed, 22 Apr 2026 10:08:06 GMT</lastBuildDate><atom:link href="https://dillonkorman.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Running SIGPwny's First Recruiting CTF]]></title><description><![CDATA[The University of Illinois' security club hosted its first beginner capture the flag event. I write about the challenges of running it and how it went.]]></description><link>https://dillonkorman.com/running-sigpwnys-first-recruiting-ctf/</link><guid isPermaLink="false">63453afdd268c528c052b3e3</guid><category><![CDATA[ctf]]></category><dc:creator><![CDATA[Dillon Korman]]></dc:creator><pubDate>Mon, 16 Sep 2019 19:13:13 GMT</pubDate><media:content url="https://dillonkorman.com/content/images/2023/05/room_1984.webp" medium="image"/><content:encoded><![CDATA[<img src="https://dillonkorman.com/content/images/2023/05/room_1984.webp" alt="Running SIGPwny&apos;s First Recruiting CTF"><p>As part of improving the University of Illinois&apos; security club, SIGPwny, the senior and lead members decided to host a capture the flag event near the start of the fall semester to recruit new students, particularly freshmen, to the club.</p><p>We had improved attendance and member involvement the previous year primarily because of a changed meeting format, expansion of club activities, and delegation of work to additional members. Additional membership allows us to teach security to more people and acquire resources that increase what we can do. Reaching freshmen is essential because it will enable them to develop into excellent and knowledgeable leaders for the club, ensuring the club will be well-run in the future. It may also lead them to discover a passion for security, creating more talent for the security community.</p><p>Hosting any CTF is no easy feat, but ours was especially challenging since it was intended to be large-scale (100+ students), in-person, and easily accessible to first-time players. Even though we knew it would be a difficult undertaking, and it did end up taking a lot of hard work from many members, we felt it would all be worth it in the end.</p><p>First, we needed sponsors. Although all the members did work for free and we used open-source software on our existing infrastructure, we needed money for food and prizes, like any other computer science competition at our school. Fortunately, we could leverage the connections of students and alumni to obtain sponsorships that gave us the requisite cash to run the event well. We invited security engineers to help us walk around and teach the students. The engineers were great since they could help beginners with challenges, test our problems to see if they worked as intended, and expose our students to job opportunities in security.</p><p>Logistically, there were many things we had to worry about since we were hosting this in person. The time, date, and location of the event were crucial. We decided that the weekend afternoon near the start of the fall semester was ideal. Students would have learned about our club through an open house, wouldn&apos;t have much homework or any exams, and likely would be awake and free to work.</p><p>Our best options for a room location were in the CS or ECE buildings. We managed to secure the main lecture hall in our CS building, which was great since there would be ample space. However, since &quot;the architects just screwed up,&quot; in the words of one CS professor, this room had very few outlets. Fortunately, we obtained many power strips right before the event to help deal with the issue and let people hack for hours on end.</p><p>The food of choice for any CS event is pizza since everyone loves pizza and you can get it delivered to you quickly. We used the ACM discount to order a large number of pizzas shortly before the event, but with enough lead time for the order. There was one wave of pizzas at the start and another in the middle. We also provided cookies (including some in Illini blue and orange) and soda. The prizes were ordered online and picked up before we distributed them.</p><p>The CTF was five hours, which provided enough time to solve many challenges. We decided to have short presentations of around ten minutes each for our main CTF categories: web, pwn/reverse engineering, crypto, recon, and forensics. Since our regular meetings are a short presentation followed by work on challenges, it was like five meetings in one event. These presentations were intended to teach students some of the basics of each category and help them solve the challenges.</p><p>Since there were beginners, and we wanted to encourage learning, we needed the members who were running the CTF and the security engineers to help people through problems. In our usual meetings, we have fewer people trying to solve the challenges, and collaboration among everyone is encouraged. Because of this and the more intimate environment, we can help everyone without much issue.</p><p>However, since we were at a larger scale than usual and there were different categories that not every member knew well, I thought using our school&apos;s website for queues would be nice. We had mixed thoughts on this since we believed walking up to people or responding to raised hands would be best. We were able to create the queue and start it before the event. We briefly mentioned it in one of the introduction slides but didn&apos;t put the queue up on the large projected screen since someone scrapped the idea shortly after.</p><p>Students were still using the queue, however, so we responded to requests. It worked well overall, especially since members knew which questions they could answer. Sometimes we couldn&apos;t figure out where the person in the room was given their description, and we couldn&apos;t follow up with a question. It is worth trying again in the future for large-scale events.</p><p>We needed to decide if we would allow teams, and if so, what would be the maximum team size allowed? There were two opposing forces at play here. As a club, we care about learning and want members to work together to solve problems. This mindset is behind why we help members extensively during a regular meeting and encourage collaboration then. However, we can&apos;t allow unlimited collaboration for this event since we wouldn&apos;t have a fair way of handing out prizes.</p><p>If people participated by themselves, prize distribution would be more straightforward, but there would be no one to work with on challenges. If there were relatively large team sizes, it would be challenging to figure out how to split a physical prize with different people on the team. Fixing this issue would require every team member to get a prize, resulting in just a few groups winning anything. Since we wanted some teamwork but many teams to win and participants to get exposure to different categories, we decided to let people work as partners.</p><p>There remained another crucial issue with teams and prize distribution. We intended the CTF to be for beginners, but we also wanted more advanced students to play. We wanted to ensure that beginners had a fair chance at earning prizes and that we prioritized when appropriate, so we split the teams into beginner and advanced categories. If either player on a team was advanced, then the team was considered advanced.</p><p>Advanced players were those who completed our school&apos;s main security course or the primary systems courses in CS or ECE, attended several SIGPwny meetings, or were otherwise advanced at either their own or the event leads&apos; discretion. During the event, we noticed a couple of beginner teams at the top in the beginning. After talking with them, we put them in the advanced category since they had experience. The top four beginner and advanced teams were awarded prizes in a back-and-forth manner, with the best beginner team getting to pick first. Each team member could choose whatever they wanted from the available prizes. We had a few extra prizes that we awarded to the fifth and sixth-best beginner teams.</p><p>We needed to do some marketing for our event to ensure people would come, so we posted about the event on Facebook, Twitter, and Reddit. We also printed lovely flyers and posted them in various buildings near the engineering quad. The most important aspects of our event that would get people to come were free food, prizes, and the beginner-friendly environment, so all of our ads mentioned them. The event was advertised as a &quot;HACKathon&quot; since more people were familiar with that term than &quot;capture the flag,&quot; and it&apos;s one of the only hackathons with actual hacking.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://dillonkorman.com/content/images/2023/05/poster.png" class="kg-image" alt="Running SIGPwny&apos;s First Recruiting CTF" loading="lazy" width="652" height="846" srcset="https://dillonkorman.com/content/images/size/w600/2023/05/poster.png 600w, https://dillonkorman.com/content/images/2023/05/poster.png 652w"><figcaption>Our wonderful poster</figcaption></figure><p>Operationally, we needed to create and host challenges. Most of the problems were required to be accessible to first-time players, but we also wanted more difficult ones that advanced players could try. We had the typical CTF categories, but pwn and reverse engineering were one combined category since they are hard for new players. We also added recon and shell, since they are more accessible, and a scavenger hunt category with flags hidden inside the room and building to motivate people to move around.</p><p>Club members submitted challenges to a Git repository, and we tried to track them on a spreadsheet. We could have done a better job of having a standardized challenge format and keeping track of all the challenges on the spreadsheet. Some challenges repeated the solve techniques of other problems, which wasn&apos;t a big deal for a beginner CTF, but we should coordinate each category&apos;s challenges next time. I think we had a solid mix of each challenge type, but we could have made the number of problems per category more balanced.</p><p>An unexpected difficulty was deciding on the points for each challenge and a scoring system. There&apos;s the traditional CTF point system where every problem has a static point value, but there&apos;s another system where the point value can decrease based on the number of solves. There are some advantages to the latter model, namely that point values adjust nicely if one challenge is more straightforward than anticipated. However, we chose static because I think it would be confusing and demoralizing for beginners to see their team losing points in the middle of the competition. They should be worried about the challenges, not continually monitoring their score.</p><p>It was hard to come up with reasonable point values for each challenge because we designed them for beginners, and we had many problems to compare each challenge against. Ultimately, we just reviewed each challenge and put what we thought was okay. The unsolved challenges got 4x the points halfway through the competition to encourage solving them, but that definitely shouldn&apos;t be done in the future. A few crypto problems were likely unsolved because of how many crypto challenges we created. Teams needed to solve all of them to earn a top spot since they were now worth a ton of points.</p><p>For our infrastructure, we ran everything off of one physical server. We used two virtual machines, one running the CTFd site and another hosting the challenges, typically web and pwn. Docker was used extensively since it makes infrastructure more flexible. CTFd can easily be installed using Docker and just requires modification of the Nginx reverse proxy for our specific configuration. Our challenge server had another reverse proxy to proxy requests to the particular web app or pwn process.</p><p>Challenges each ran in their own Docker container. It&apos;s easier to write problems if you know the execution environment. There&apos;s also no need to worry about typical security configurations since you shouldn&apos;t be able to break out of a standard container. If we decide to use a different server in the future or want to share the challenge, it&apos;s much easier to deploy again. Containers are also easier to maintain and set up compared to virtual machines or physical servers.</p><p>Despite all the logistical and operational challenges, the CTF went great overall. We had 112 players, and it seemed like most people stayed for the entire event, which is awesome. There was plenty of food, and I even got to take home a pizza. The security engineers were impressed it went so well, especially since this was our first event of its kind, and undergrads organized it.</p><p>We solicited some feedback about the event on a Google Forms questionnaire via email and a Discord announcement. Respondents overwhelmingly said they enjoyed the competition, thought the prizes were cool, and found the club members and engineers helping to be useful. About half agreed the presentations were useful, and many had neutral thoughts. I agree that they could be improved, and it&apos;s worth asking for more detailed feedback on that. Players generally thought the prize distribution was fair, and the event length was about right.</p><p>I thought the event length was solid since there were always plenty of challenges to work on, but we were pretty tired by the end, so I don&apos;t believe we should extend it. The favorite CTF categories were actually split pretty evenly, so it&apos;s nice we had every category. Someone thought it wasn&apos;t beginner-friendly enough since there was no cross-team collaboration, and some of the assistance wasn&apos;t specific enough. These are valid points, and we should consider standardizing how we assist players.</p><p>In conclusion, I&apos;m happy we had this event. People seemed to enjoy it, and there were a lot of thankful comments as feedback, which made our effort worth it. All the members who helped run the event learned a ton too. Interest in the club and meeting attendance is at an all-time high, so we&apos;re able to teach many more people now. SIGPwny is in an excellent state, and I know all will be well when I graduate.</p>]]></content:encoded></item><item><title><![CDATA[CSAW 2018 WhyOS Writeup]]></title><description><![CDATA[This is a writeup of the WhyOS challenge at CSAW 2018. ]]></description><link>https://dillonkorman.com/csaw-2018-whyos/</link><guid isPermaLink="false">63453afdd268c528c052b3e2</guid><category><![CDATA[ctf]]></category><category><![CDATA[writeup]]></category><category><![CDATA[csaw]]></category><category><![CDATA[forensics]]></category><dc:creator><![CDATA[Dillon Korman]]></dc:creator><pubDate>Mon, 17 Sep 2018 05:17:04 GMT</pubDate><content:encoded><![CDATA[<p>This is a forensics challenge worth 300 points. </p><p>We are given an iPhone application and a debug log with 185k lines. </p><p>My team originally solved this challenge by running the application on a jailbroken iPhone and observing the debug log from that session, but the prompt said that no device was needed, so I set out to find an alternative but reasonable solution method based on information I already had. </p><p>I spent a lot of time searching for certain strings, but I instead could have searched simply for an uncommon logging format. There was an hint released later that I didn&apos;t see but definitely would have helped. However, this method works without that hint. </p><p>I first wanted to take a look inside the application, so I extracted it and looked at the extracted files.</p><!--kg-card-begin: markdown--><pre><code>dpkg-deb -x com.yourcompany.whyos_4.2.0-28debug_iphoneos-arm.deb app
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><pre><code>root@kali:~/csaw/app# ls */*/*
Library/MobileSubstrate/DynamicLibraries:
whyOS.dylib  whyOS.plist

Library/PreferenceBundles/whyOSsettings.bundle:
Info.plist  Root.plist  whyOSsettings

Library/PreferenceLoader/Preferences:
whyOSsettings.plist
</code></pre>
<!--kg-card-end: markdown--><p>There appeared to be two binary files and four property list files. Two strings from those files that appeared interesting were <strong>com.yourcompany.whyossettings</strong> and <strong>CSAWRootListController</strong> along with those in Root.plist more generally. </p><p>However, when I searched for <strong>whyOS</strong> in the debug log, I was very surprised to only find two lines that contained that term, considering how important and broad it seemed.</p><p>I searched for <strong>CSAWRootListController</strong> along with other interesting terms in Root.plist, but I had no results. There were too many instances of <strong>flag</strong> for me to browse. </p><p>I looked for several hundred lines above and below the <strong>whyOS </strong>matches because I thought that&apos;s where the activity happened, but I did not find anything useful. </p><p>I ran strings on the binaries, but didn&apos;t find anything that would lead to the flag, so I decided to take a look closer look in IDA, even though this wasn&apos;t a reversing challenge, which made me unsure if I was on the right track. </p><p>I looked at <strong>whyOS.dylib</strong>, but it basically didn&apos;t contain anything, so I moved on to the other file. </p><p>There are two functions, <strong>specifiers</strong> and <strong>setflag</strong>. I decompiled them with IDA to get a better look at what they do. </p><!--kg-card-begin: markdown--><pre><code>id __cdecl -[CSAWRootListController specifiers](struct CSAWRootListController *self, SEL a2)
{
  void *v2; // r0@2
  struct CSAWRootListController *v4; // [sp+10h] [bp-Ch]@1

  v4 = self;
  if ( !*(_DWORD *)&amp;self-&gt;PSListController_opaque[OBJC_IVAR___PSListController__specifiers] )
  {
    v2 = objc_msgSend(self, &quot;loadSpecifiersFromPlistName:target:&quot;, CFSTR(&quot;Root&quot;), self);
    *(_DWORD *)&amp;v4-&gt;PSListController_opaque[OBJC_IVAR___PSListController__specifiers] = objc_msgSend(v2, &quot;retain&quot;);
  }
  return *(id *)&amp;v4-&gt;PSListController_opaque[OBJC_IVAR___PSListController__specifiers];
}
</code></pre>
<!--kg-card-end: markdown--><p>This method just looks like it loads specifiers from Root.plist, which may be useful for the program but isn&apos;t that interesting for us since that&apos;s all it does. </p><p>The <strong>setflag</strong> method obviously sounds more interesting for us. </p><!--kg-card-begin: markdown--><pre><code>void __cdecl -[CSAWRootListController setflag](struct CSAWRootListController *self, SEL a2)
{
  void *v2; // r0@1
  __CFString *v3; // [sp+4h] [bp-34h]@2
  void *v4; // [sp+20h] [bp-18h]@1

  v2 = objc_msgSend(&amp;OBJC_CLASS___NSMutableDictionary, &quot;alloc&quot;);
  v4 = objc_msgSend(v2, &quot;initWithContentsOfFile:&quot;, CFSTR(&quot;/var/mobile/Library/Preferences/com.yourcompany.whyos.plist&quot;));
  if ( objc_msgSend(v4, &quot;objectForKey:&quot;, CFSTR(&quot;flag&quot;)) )
    v3 = (__CFString *)objc_msgSend(v4, &quot;objectForKey:&quot;, CFSTR(&quot;flag&quot;));
  else
    v3 = &amp;stru_8044;
  NSLog(CFSTR(&quot;%@&quot;), v3);
}
</code></pre>
<!--kg-card-end: markdown--><p>It looks like the function creates a dictionary from the whyos.plist file and looks for the value for the key <strong>flag</strong>. If it exists, it sets a string variable to that value. Otherwise, that string is set to what is actually an empty string. </p><p>Finally, and most importantly, it logs the string to the console. </p><p>I looked online for the default NSLog output format and discovered the format. </p><!--kg-card-begin: markdown--><pre><code>Date Time OurApp[&lt;process&#xAD;id&gt;] output
</code></pre>
<!--kg-card-end: markdown--><p>Since the NSLog call is just printing out the string, which is the flag, with no extra parameters, we can expect our output to be in a known format.</p><!--kg-card-begin: markdown--><pre><code>X Y Z flag
</code></pre>
<!--kg-card-end: markdown--><p>Looking through the debug log, the lines are incredibly verbose, so having just one word might stand out. Additionally, we know the flag is not in the standard <strong>flag{}</strong> format from the description. </p><p>I would say flags are generally at least 10 characters long, and since there are no curly brackets, may just contain alphanumeric characters, although there could still be underscores. </p><p>We can take a look at some example lines from console log.</p><!--kg-card-begin: markdown--><pre><code>default 18:59:15.308337 -0400   nsurlsessiond   [5757 &lt;private&gt; stream, bundle id: mobileassetd, pid: 386, url...
default 18:59:15.308698 -0400   nsurlsessiond   0.000s [5757 E6368DF7-4A60-45CF-A579-4C1AF76AE40E &lt;private&gt; ...
error   18:59:15.308772 -0400   nsurlsessiond   Task &lt;A4B92146-9429-451D-B0FC-88C778AE5177&gt;.&lt;29&gt; finish...
default 18:59:15.308823 -0400   nsurlsessiond   0.000s [5757 E6368DF7-4A60-45CF-A579-4C1AF76AE40E &lt;private&gt; p...
default 18:59:15.309335 -0400   nsurlsessiond   0.000s [5757 E6368DF7-4A60-45CF-A579-4C1AF76AE40E &lt;private&gt; p...
default 18:59:15.309412 -0400   nsurlsessiond   0.000s [5757 E6368DF7-4A60-45CF-A579-4C1AF76AE40E &lt;private&gt; ...
default 18:59:15.309464 -0400   nsurlsessiond   10.801s [5757] path:cancel
</code></pre>
<!--kg-card-end: markdown--><p>We want to get the part that the application actually logs, not the metadata at the start. We can use <strong>cut</strong> to get that part, but first we need to remove the extra spaces using <strong>tr</strong> before the application logging so we can easily make a single space as a delimiter for <strong>cut</strong>. </p><!--kg-card-begin: markdown--><p><code>tr -s &apos;[:space:]&apos; &lt; console.log | cut -d&quot; &quot; -f5- </code></p>
<!--kg-card-end: markdown--><p>Now that we have the application part, we are only interested in what might be our flag. Based on our previous criteria, we search for 10 or more alphanumeric characters at the start of a line followed by the end of a line. </p><!--kg-card-begin: markdown--><p><code>tr -s &apos;[:space:]&apos; &lt; console.log | cut -d&quot; &quot; -f5- | grep -E &apos;^[[:alnum:]]{10,}$&apos;</code></p>
<!--kg-card-end: markdown--><p>We see that there are only 296 lines of one word as output, which we can easily look at quickly for anything interesting. </p><!--kg-card-begin: markdown--><pre><code>root@kali:~/csaw# tr -s &apos;[:space:]&apos; &lt; console.log | cut -d&quot; &quot; -f5- | grep -E &apos;^[[:alnum:]]{10,}$&apos; | wc -l
296
</code></pre>
<!--kg-card-end: markdown--><p>There are a lot of technical and repeated terms, but in the noise we see a clear outlier. </p><!--kg-card-begin: markdown--><pre><code>postPearlInterlockFollowUpItem
DeviceDiscoveryActivate
DeviceDiscoveryActivate
DeviceDiscoveryUpdate
postPearlInterlockFollowUpItem
postPearlInterlockFollowUpItem
keybagDidUnlock
ca3412b55940568c5b10a616fa7b855e
postPearlInterlockFollowUpItem
Invalidating
Invalidated
</code></pre>
<!--kg-card-end: markdown--><p>There appears to be a hash! </p><p>If we search for this in the debug log, we find the line.</p><!--kg-card-begin: markdown--><pre><code>root@kali:~/csaw# grep -n &apos;ca3412b55940568c5b10a616fa7b855e&apos; console.log 
97190:default 19:12:18.884704 -0400   Preferences ca3412b55940568c5b10a616fa7b855e
</code></pre>
<!--kg-card-end: markdown--><p>The application is <strong>Preferences</strong>, which makes sense since this appears to be a settings or preferences related application. </p><p>The flag is <strong>ca3412b55940568c5b10a616fa7b855e</strong>.</p><p>Overall, I did not really enjoy this challenge. The moderator of the challenge on chat noted that the application was &quot;littered with hints&quot; about where to look, but I disagree. </p><p>The hint that it was a hex string made it more reasonable, but that hint came late and the challenge still remained a &quot;grepping&quot; challenge. We had to use a jailbroken iPhone before the hint to find the flag, which should not have felt like it was important when the challenge explicitly said a device was not needed. </p><p>Anyway, I&apos;m glad I came up with an alternative way, but I think I was too focused looking for a keyword or something else in the debug log that would hint at the location to think of a method of filtering by format. </p>]]></content:encoded></item><item><title><![CDATA[CSAW 2018 🐼 Rewind Writeup]]></title><description><![CDATA[This is a writeup of the 🐼 Rewind challenge at CSAW 2018.]]></description><link>https://dillonkorman.com/csaw-2018-rewind-writeup/</link><guid isPermaLink="false">63453afdd268c528c052b3e1</guid><category><![CDATA[ctf]]></category><category><![CDATA[writeup]]></category><category><![CDATA[csaw]]></category><category><![CDATA[forensics]]></category><dc:creator><![CDATA[Dillon Korman]]></dc:creator><pubDate>Sun, 16 Sep 2018 20:48:22 GMT</pubDate><content:encoded><![CDATA[<p>This is a forensics challenge worth 200 points. </p><p>We are given a tar archive for the challenge that we can extract.</p><!--kg-card-begin: markdown--><pre><code>root@kali:~/csaw/rewind# tar -xvf rewind.tar.gz 
rewind.zip
</code></pre>
<!--kg-card-end: markdown--><p>We can now extract this zip archive. </p><!--kg-card-begin: markdown--><pre><code>root@kali:~/csaw/rewind# unzip rewind.zip 
Archive:  rewind.zip
  inflating: rewind-rr-nodent.log    
  inflating: rewind-rr-snp
</code></pre>
<!--kg-card-end: markdown--><p>We can take a look at what these files are with the file utility. </p><!--kg-card-begin: markdown--><pre><code>root@kali:~/csaw/rewind# file *
rewind-rr-nodent.log: data
rewind-rr-snp:        QEMU suspend to disk image
</code></pre>
<!--kg-card-end: markdown--><p>We can first try to search for the flag within the image with a regular expression.</p><!--kg-card-begin: markdown--><pre><code>root@kali:~/csaw/rewind# grep -a &quot;flag{.*}&quot; rewind-rr-snp
...
flag{RUN_R3C0RD_ANA1YZ3_R3P3AT}
...
</code></pre>
<!--kg-card-end: markdown--><p>Success! That was all that was required to complete this challenge. </p><p>Overall, this was an extremely simple challenge that only required extracting two archives and performing a simple search for the flag in the image. </p>]]></content:encoded></item><item><title><![CDATA[CSAW 2017 Missed Registration Writeup]]></title><description><![CDATA[This is a writeup of the Missed Registration challenge at CSAW 2017.]]></description><link>https://dillonkorman.com/csaw-2017-missed-registration-writeup/</link><guid isPermaLink="false">63453afdd268c528c052b3e0</guid><category><![CDATA[ctf]]></category><category><![CDATA[writeup]]></category><category><![CDATA[csaw]]></category><category><![CDATA[forensics]]></category><dc:creator><![CDATA[Dillon Korman]]></dc:creator><pubDate>Mon, 18 Sep 2017 04:01:13 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>This is a forensics challenge worth 150 points.</p>
<p>We are given a pcap file to analyze. After opening it up in Wireshark, we can follow the TCP streams to get a feel of what&apos;s going on.</p>
<p>Browsing through the streams, we notice there is a lot of HTTP traffic for school registration. The requests are mostly the same with random fields for names, schools, and courses. The responses all appear to be the same.</p>
<p>Briefly looking at the other traffic in the pcap suggests there is not anything else too interesting for this challenge. The challenge description mentions registration and these forms, so it&apos;s very likely the answer is in this HTTP traffic somewhere.</p>
<p>Since the responses all appear the same, let&apos;s focus on the requests. The headers change slightly for some of the requests. Most of the requests have these headers:</p>
<pre><code>POST / HTTP/1.1
Host: 192.168.0.21:8080
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.11.1
Content-Length: 506
Content-Type: application/x-www-form-urlencoded
</code></pre>
<p>While some of the requests have these headers.</p>
<pre><code>POST / HTTP/1.1
Host: 192.168.0.21:8080
Accept-Encoding: identity
Content-Length: 493
Content-Type: application/x-www-form-urlencoded
</code></pre>
<p>Basically, one request is asking for compression and one isn&apos;t. This could be something of note, but these headers don&apos;t contain the flag, so we can go back to it later.</p>
<p>Switching over to the values in the request, we see &quot;n&quot; and &quot;s&quot;. The former is a long string of hex values and the latter is a single letter from A-F. I think the latter could be for grades. At this point I thought the flag must be in &quot;n&quot;, but then I noticed that there was an &quot;x&quot; value in certain requests, those with the &quot;Accept-Encoding&quot; header of &quot;identity.&quot;</p>
<p>The hex values for &quot;n&quot; and &quot;x&quot; did not decode into ASCII. What else could they be? Well, there are enough values for a small file, so we can try looking for that.</p>
<p>I need to extract these values together into a file, turn them into a binary, and then use a tool like foremost to identify any potential files.</p>
<p>I used the following command to extract the values cleanly:</p>
<pre><code>strings cap.pcap | grep -o -f expression | sed &apos;s/&amp;x=//g&apos; | tr -d &apos;\n&apos; | sed &apos;s/[^A-Fa-f0-9]//g&apos; &gt; output.txt
</code></pre>
<p>where &quot;expression&quot; is a file with contents (here, it&apos;s &quot;x&quot;, but it could be &quot;n&quot; as well):</p>
<pre><code>&amp;x=.*
</code></pre>
<p>Broken down, strings is grabbing the text of the pcap, grep is only extracting content that matches the regular expression in the file &quot;expression,&quot; which is just the value syntax &quot;&amp;x=&quot; followed by a regular expression, &quot;.*&quot;, to match whatever comes after that syntax. Next, sed is removing the value syntax, &quot;&amp;x=&quot;, tr is removing new lines, and sed is removing any non-hex values.</p>
<p>To convert these hex values from a string to values in a binary, we can use a short Python script.</p>
<pre><code>string_hex_file = open(&quot;output.txt&quot;, &quot;r&quot;)
hex_as_string = string_hex_file.read()

hex_as_binary = hex_as_string.decode(&quot;hex&quot;)
binary_hex_file = open(&quot;binary&quot;, &quot;w+&quot;)
binary_hex_file.write(hex_as_binary)

string_hex_file.close()
binary_hex_file.close()
</code></pre>
<p>We simply open our output file, read the bytes as hex, and write them to a new file.</p>
<p>Now, we can use a tool like foremost to extract any files that might be in there.</p>
<pre><code>root@kali:/opt/ctf/csaw17# foremost -i binary
Processing: binary
|*|
</code></pre>
<p>It looks like it found a bmp file, which could be an image with the flag. Let&apos;s check it out!</p>
<pre><code>root@kali:/opt/ctf/csaw17/output# ls
audit.txt  bmp
root@kali:/opt/ctf/csaw17/output# ls bmp
00000000.bmp
root@kali:/opt/ctf/csaw17/output# eog bmp/00000000.bmp 
</code></pre>
<p><img src="https://dillonkorman.com/content/images/2023/05/registration_flag.png" alt="registration_flag" loading="lazy"></p>
<p>Success!</p>
<p>It was pretty apparent quickly that the flag was likely somewhere in the HTTP requests, but it took time to spot the &quot;x&quot; value (since it was only in some requests and somewhat hidden after the &quot;n value&quot;) and then to realize there could be a file header inside. Overall, this was a fun and interesting challenge.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[CSAW 2017 Best Router Writeup]]></title><description><![CDATA[This is a writeup of the Best Router challenge at CSAW 2017.]]></description><link>https://dillonkorman.com/csaw-2017-best-router-writeup/</link><guid isPermaLink="false">63453afdd268c528c052b3df</guid><category><![CDATA[ctf]]></category><category><![CDATA[writeup]]></category><category><![CDATA[csaw]]></category><category><![CDATA[forensics]]></category><dc:creator><![CDATA[Dillon Korman]]></dc:creator><pubDate>Sun, 17 Sep 2017 23:02:54 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>This was a simple forensics challenge worth 200 points.</p>
<p>We are given an archive which we can easily extract.</p>
<pre><code>root@kali:/opt/ctf/csaw17/best_router# tar -xvf best_router.tar.gz 
tar: Ignoring unknown extended header keyword &apos;LIBARCHIVE.creationtime&apos;
tar: Ignoring unknown extended header keyword &apos;SCHILY.dev&apos;
tar: Ignoring unknown extended header keyword &apos;SCHILY.ino&apos;
tar: Ignoring unknown extended header keyword &apos;SCHILY.nlink&apos;
best_router.img
</code></pre>
<p>We can now run binwalk on it to analyze the firmware.</p>
<pre><code>root@kali:/opt/ctf/csaw17/best_router# binwalk best_router.img

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
4886543       0x4A900F        Copyright string: &quot;copyright does *not* cover user programs that use kernel&quot;
...
4905514       0x4ADA2A        Copyright string: &quot;Copyright (c) 2015, Raspberry Pi (Trading) Ltd&quot;
</code></pre>
<p>Looking at this output, we can see that it&apos;s a Raspberry Pi device, which we can mount by following <a href="https://raspberrypi.stackexchange.com/questions/13137/how-can-i-mount-a-raspberry-pi-linux-distro-image?ref=dillonkorman.com">this guide</a>.</p>
<pre><code>root@kali:/opt/ctf/csaw17/best_router# fdisk -l best_router.img
Disk best_router.img: 14.6 GiB, 15640559616 bytes, 30547968 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7f39f284

Device           Boot Start      End  Sectors  Size Id Type
best_router.img1       8192    93813    85622 41.8M  c W95 FAT32 (LBA)
best_router.img2      94208 30547967 30453760 14.5G 83 Linux
</code></pre>
<p>We can now mount the device after calculating the offset.</p>
<pre><code>root@kali:/opt/ctf/csaw17/best_router# mount -v -o offset=48234496 -t ext4 best_router.img /mnt/img/router
mount: /dev/loop0 mounted on /mnt/img/router.
</code></pre>
<p>After we have mounted it, we can go exploring. I first looked at the /home/ directory and found the &quot;pi&quot; user. We can take a look at the bash history.</p>
<pre><code>root@kali:/mnt/img/router/home/pi# cat .bash_history 
ls
sudo su
</code></pre>
<p>It looks like they switched to root, so let&apos;s check there.</p>
<pre><code>root@kali:/mnt/img/router/root# cat install.sh 
sudo apt-get update
sudo apt-get install apache2 -y
sudo a2enmod cgid

sudo cp 000-default.conf /etc/apache2/sites-available/000-default.conf
sudo service apache2 restart

sudo rm -rf /var/www/*
sudo mv www/* /var/www
chmod 755 /var/www/*.pl
</code></pre>
<p>It looks like there is an installation script to install a website. Let&apos;s check what&apos;s in that directory.</p>
<pre><code>root@kali:/mnt/img/router/var/www# ls -l
total 16
-rw-r--r-- 1 root root    0 Sep 10 00:43 flag.txt
-rwxr-xr-x 1 root root  472 Sep 10 00:51 index.pl
-rwxr-xr-x 1 root root 1238 Sep 10 00:50 login.pl
-rw-r--r-- 1 1000 1000   23 Sep 10 00:49 password.txt
-rw-r--r-- 1 1000 1000    5 Sep 10 00:49 username.txt
</code></pre>
<p>There is an empty flag file, but there are username and password files.</p>
<pre><code>root@kali:/mnt/img/router/var/www# cat username.txt
admin
root@kali:/mnt/img/router/var/www# cat password.txt 
iforgotaboutthemathtest
</code></pre>
<p>These look useful. Let&apos;s try them on the website they gave us in the challenge prompt.</p>
<pre><code>Authenticated

flag{but_I_f0rgot_my_my_math_test_and_pants}
</code></pre>
<p>Success!</p>
<p>Overall, this was a pretty simple forensics problem that required mounting the image and exploring the file system for the value content.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>