<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[r3dey3]]></title><description><![CDATA[WH3N W0RLDS C0LL1DE]]></description><link>https://www.r3dey3.com/</link><image><url>https://www.r3dey3.com/favicon.png</url><title>r3dey3</title><link>https://www.r3dey3.com/</link></image><generator>Ghost 4.48</generator><lastBuildDate>Tue, 16 Sep 2025 16:00:08 GMT</lastBuildDate><atom:link href="https://www.r3dey3.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Backup Implementation]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I figured it&apos;s been a few weeks since I put my thoughts to keyboard regarding various backup solutions and since I&apos;ve decided on a one and it&apos;s been in use for a week or two now it&apos;s time to write up what</p>]]></description><link>https://www.r3dey3.com/backup-implementation/</link><guid isPermaLink="false">5ad628e9851f9800016ae78a</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Thu, 14 Sep 2017 02:06:03 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I figured it&apos;s been a few weeks since I put my thoughts to keyboard regarding various backup solutions and since I&apos;ve decided on a one and it&apos;s been in use for a week or two now it&apos;s time to write up what I went with.</p>
<p>The short answer is <a href="https://restic.github.io/">Restic</a>, <a href="https://www.arqbackup.com">Arq</a> and <a href="https://rclone.org">Rclone</a> for software and <a href="https://www.backblaze.com/b2/">Backblaze B2</a> for cloud storage.</p>
<h2 id="systems">Systems</h2>
<p>I have multiple systems that need backed up:</p>
<ul>
<li>My parents&apos; laptop (at their house)</li>
<li>My parents&apos; desktop (at their house)</li>
<li>My local fileserver</li>
<li>My laptop</li>
<li>My wife&apos;s surface pro</li>
<li>My two <a href="https://www.linode.com/?r=80eb7282fa375b94f0e5d2726f61f9d98af0f7a9">Linode</a> servers</li>
</ul>
<p>I also have a server that is used to store backups at my parents house. It doesn&apos;t do any backups itself, but will be used for syncing.</p>
<p>The ultimate goal for all backups is to have three backup locations for critical data in addition to the original source:</p>
<ol>
<li>Fileserver at my house</li>
<li>Fileserver at my parents</li>
<li>Cloud storage</li>
</ol>
<h2 id="arq">Arq</h2>
<p>This is probably the simplest to describe as it&apos;s almost an all in one solution.<br>
Configuration:</p>
<ul>
<li>sftp destination to the local fileserver at each location, using a per-laptop user account and strong password.</li>
<li>Email notification on errors using a gmail account I have on my domain for such purposes.</li>
<li>For my parents&apos; systems - every 4 hours</li>
<li>For my wife&apos;s every hour</li>
<li>Prune hourly/daily/weekly/monthly option to hopefully limit the amount of space empty backups use.</li>
<li>All systems backup c:\users and c:\programdata. I spent a little bit of time removing things that generate a bunch changes even when the system isn&apos;t in use (e.g. Cache, Antivirus)</li>
</ul>
<p>While using the local fileserver as a backup destination means the systems will not be backed up when outside of the house, it is very rare that those systems are used outside of the house.</p>
<h2 id="restic">Restic</h2>
<p>I chose restic because it seemed to be the fastest solution that supported cloud destinations that I could find during my trials.</p>
<p>Originally I performed a full backup of my fileserver to Backblaze B2 but upon thinking about how I wanted to sync I decided to backup to a local path instead. So I spent a few hours downloading the archive using rclone. I then configured my laptop to backup to the same location over sftp. This means that the deduplication is effective when I move data from my laptop to my fileserver for permanent storage.</p>
<p>I then configured the restic <a href="https://github.com/restic/rest-server"><code>rest-server</code></a> for my two Linode servers. I made a simple modification the the server to enable append-only mode, meaning while the servers can create new backups they cannot remove or modify existing backups; providing &quot;hack&quot; protection of sorts as the credentials to access the backup are on the servers. To provide a simple implementation I added a sub-domain to one of my domains for backup and configured one of the servers to reverse proxy the connection over a vpn to my local fileserver. This means that the backups are stored on my local fileserver, but the destination is accessible at a fixed hostname over ssl (thank&apos;s <a href="https://letsencrypt.org/">letsencrypt</a>).</p>
<p>After a few days I ran into an issue with my local fileserver and laptop backups due to linux permissions. The fileserver was using the root user for backup (yah, yah.. I&apos;m lazy) but the laptop used a non-root user for stfp. I eventually configured two different <code>rest-server</code>s; one that listed on localhost and another that listens on the local interface in append only mode.</p>
<h3 id="scheduling">Scheduling</h3>
<p>As restic is a simple app that does not implement its own scheduling I fell back on a simple cron script to do the backup. I first configured <code>postfix</code> to use <a href="https://www.mailgun.com/">mailgun</a> using a <a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-mail-relay-with-postfix-and-mailgun-on-ubuntu-16-04">tutorial on digitalocean</a>. I then installed <code>cronic</code> to curb the amount of email as I only need notification when something fails. For my fileserver I just added a new line in cron to run my backup script, but for my Linode servers and laptop, I wanted to just drop a script into /etc/cron.daily to run. In order for the script to run through cronic I had to do a bit of magic at the start</p>
<pre><code>in_cronic=$1
if [[ &quot;$in_cronic&quot; != &apos;in_cronic&apos; ]]; then
	exec cronic $0 in_cronic
fi

set -xeu
</code></pre>
<h2 id="rclone">rclone</h2>
<p>The last feature I wanted was to sync the backups to the other locations. Using rclone I configured a Backblaze B2 endpoint, and then used the copy command to sync the backups. I might eventually switch to the sync command for the Arq destinations if I notice the space growing significantly.</p>
<p>Another feature of rclone I took advantage of is the ability to sync Google Drive. I configured endpoints for both my wife and my accounts and now sync them on the fileserver prior to performing the backup; never hurts to have extra copies of stuff.</p>
<p>One thing I ran into while trying to push the backup to my parents house was their slow internet speed; so I spent $70 on an <a href="http://a.co/iuRLTYZ">external hard drive</a> to copy the backup to and then snail-mail to my parents. This turned out to be way faster than doing the sync over the internet as the speed would be limited to approx 1Mbit/s. With my 1.3TB of data it would have taken over 100 days. Whereas I was able to get the data transferred to the hard drive and mailed and transferred off in less than a week. I then copied their data onto the hard drive and then they mailed it back to me.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Backup Search Results]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Just my thoughts on the various backup packages - updated as I evaluate them more.</p>
<h4 id="spideroakone">Spideroak One</h4>
<ul>
<li>Super simplistic interface.</li>
<li>No way to start/stop backups, only able to run them on schedule</li>
<li>couldn&apos;t tell if there was archival of versions</li>
<li>proprietary storage server</li>
<li>linux install is just</li></ul>]]></description><link>https://www.r3dey3.com/backup-search-results/</link><guid isPermaLink="false">5ad628e9851f9800016ae789</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Sun, 27 Aug 2017 16:03:54 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Just my thoughts on the various backup packages - updated as I evaluate them more.</p>
<h4 id="spideroakone">Spideroak One</h4>
<ul>
<li>Super simplistic interface.</li>
<li>No way to start/stop backups, only able to run them on schedule</li>
<li>couldn&apos;t tell if there was archival of versions</li>
<li>proprietary storage server</li>
<li>linux install is just untar a file onto / (NOT the way to go)</li>
</ul>
<h4 id="idrive">iDrive</h4>
<ul>
<li>No UI for linux; I don&apos;t feel like figuring out the scripts for</li>
</ul>
<h4 id="duplicity">Duplicity</h4>
<ul>
<li>Slow as dirt</li>
<li>incremental downloads rely on last full?</li>
<li>linux only</li>
</ul>
<h4 id="duplicacy">Duplicacy</h4>
<ul>
<li>CLI isn&apos;t very self documenting</li>
<li>cli only (linux)</li>
<li>couldn&apos;t figure out how to get it to not prompt username/password</li>
</ul>
<h4 id="qbackup">qBackup</h4>
<ul>
<li>Java</li>
<li>Just loading the UI used 300MB of memory. Scanning my home directory used over 1GB</li>
<li>Expensive</li>
<li>No built in scheduler</li>
</ul>
<h4 id="goodsync">GoodSync</h4>
<ul>
<li>Looks annoying to configure - no ui on linux</li>
</ul>
<h4 id="cloudberrybackup">CloudBerry Backup</h4>
<ul>
<li>no free version</li>
<li>filenames/paths are not encrypted on destination</li>
<li>no stfp support</li>
<li>~300MB of memory used to backup 7GB</li>
<li>completion and failure emails</li>
<li>installs all the directories as 777</li>
<li>storage is a full path and filename as a directory (with a : at the end) and then files that are named based on timestamp. (doesn&apos;t encrypt filenames)</li>
</ul>
<h4 id="urbackup">UrBackup</h4>
<ul>
<li>no crypto</li>
<li>more enterprisy</li>
<li>requires server</li>
<li>requires opening ports on the client to be discovered</li>
</ul>
<h4 id="cloudbacko">CloudBacko</h4>
<ul>
<li>Java</li>
<li>refuses to install or run as a user on linux</li>
<li>scheduler uses 120MB of memory with nothing configured</li>
</ul>
<h4 id="duplicati">duplicati</h4>
<ul>
<li>Web UI</li>
<li>.Net/mono</li>
<li>&quot;beta&quot;</li>
<li>175MB of memory used to backup 7GB</li>
<li>&quot;proprietary&quot; storage format (but open source)</li>
</ul>
<h4 id="arq">Arq</h4>
<ul>
<li>Windows/Mac only</li>
<li>easy to configure; supports s3/b2/sftp</li>
<li>runs a service to backup</li>
</ul>
<h4 id="resilio">Resilio</h4>
<ul>
<li>primary sync; used to be btsync and i nixed that one a while ago</li>
</ul>
<h4 id="syncbackpro">SyncBackPro</h4>
<ul>
<li>windows only</li>
<li>pain to configure versioning</li>
<li>couldn&apos;t get it to work with minio (it would get buckets, but fail to actually backup)</li>
</ul>
<h4 id="rclone">rclone</h4>
<ul>
<li>simple rsync like interface for s3/b2</li>
<li>good for syncing from one &apos;server&apos; to the cloud</li>
</ul>
<h4 id="restic">restic</h4>
<ul>
<li>requires a backup to complete before you can restore</li>
<li>can backup multiple hosts to same archive (does dedup across all)</li>
<li>operates a lot like git - files are referenced in snapshots</li>
<li>able to saturate my 20Mbit up with an 7 year old intel atom cpu.</li>
<li>no integrated scheduler</li>
</ul>
<h2 id="result">Result</h2>
<p>I decided to go with Arq for windows to just backup to local servers via sftp. For my fileserver I decided on restic to B2, i tried duplicati but it was very slow at backup. Setting up a cron job to backup won&apos;t be so hard, plus it will be nice to be able to different level of backups on different folders, all going to the same archive.</p>
<p>To provide redundancy I&apos;m going to use rclone to push the local backups to B2.. and once there pull them down on the other side.. even though this will cost a bit of money the first time it shouldn&apos;t be too much (maybe $30-40).</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[The hunt for a new backup solution]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>For about 2 years now I&apos;ve been using CrashPlan Family Unlimited (no link because I&apos;m mad at them) to handle backing up my data. I liked the solution well enough - it had Peer2Peer backups which meant I could install it on some less-tech-savvy friends&apos;</p>]]></description><link>https://www.r3dey3.com/backup-solution/</link><guid isPermaLink="false">5ad628e9851f9800016ae788</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Tue, 22 Aug 2017 19:06:25 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>For about 2 years now I&apos;ve been using CrashPlan Family Unlimited (no link because I&apos;m mad at them) to handle backing up my data. I liked the solution well enough - it had Peer2Peer backups which meant I could install it on some less-tech-savvy friends&apos; &amp; families&apos; computers and they would have backup. It also supported Linux and allowed multiple computers (any OS) to use the same account which meant I could back up all my stuff and my wife&apos;s (6 computers, split 3 win/3 linux). Well they recently announced they are no longer going to offer their crashplan for home service. Their solution is to either offer a deal with Carbonite (no linux support) or their CrashPlan for small business. They are offering 75% off for 1 year for their small business plan, which comes out to the same price as the old $150/yr for the family unlimited plan for the first year.. afterwords it&apos;s 4x the cost. So I&apos;ve decided they are no longer going to get another penny from me.</p>
<p>I&apos;d love to switch to <a href="https://www.backblaze.com/">Backblaze</a>, but they don&apos;t offer a Linux client, no peer2peer and the cost would be more than what I was paying previously ($50/yr/computer). So I just spend the last hour or so (so much for getting work done... thanks for nothing CrashPlan) looking at various solutions that support Windows and Linux as well as peer2peer.</p>
<p>I&apos;ve narrowed my search down to the following products. I haven&apos;t had a chance to evaluate them other than looking at their web pages.</p>
<h4 id="spideroakone"><a href="https://spideroak.com/one/">Spideroak One</a></h4>
<p>This is the only product I found that provides the cloud storage as well as the software. It supports Windows, Linux, OS X, Android and iOS (not sure if it does the backup on the mobile stuff or just access). Pricing for my storage needs would be $279/yr and it doesn&apos;t support peer2peer.</p>
<p>The rest of the solutions all use a cloud storage provider such as Amazon Glacier, Backblaze B2 or Google Coldline.</p>
<h4 id="duplicity"><a href="http://duplicity.nongnu.org/index.html">Duplicity</a></h4>
<p>Linux only, rsync like backup solution. Free, GPL. I only include this one in case I decide to go with a Backblaze for the Windows backups. <a href="http://www.duply.net/">Duply</a> is a front end. I found a guide on doing <a href="http://ddevnet.net/posts/backup-amazon-s3-2014.html">Encrypted backup to Amazon S3 (2014)</a> using duply so that might be a good starting point.</p>
<h4 id="duplicacy"><a href="https://duplicacy.com/">Duplicacy</a></h4>
<p>While similar in name to the previous one, it&apos;s not. This one supports backup to cloud storage as well as sftp so it has at least partial peer2peer support. For personal use, the CLI version is free for any OS, while the Windows/Mac GUI Pricing is reasonable at an initial $20/computer for the first year and then $5/computer after the first year. The source code for the CLI is available, but not sure of the exact license (not a standard OpenSource license). It&apos;s written in go so it shouldn&apos;t be as much of a memory hog I hope.</p>
<h4 id="qbackup"><a href="https://www.qualeed.com/en/qbackup/">qBackup</a></h4>
<p>This too support sftp and cloud storage. Pricing is $29.99 per windows/mac computer and $99.99 per linux. This is definitely a pricey option but it looks like it&apos;s only a one time fee.</p>
<h4 id="goodsync"><a href="https://www.goodsync.com/">GoodSync</a></h4>
<p>I&apos;m really turned off by their web page, and it&apos;s hard to find the information I want, but I&apos;m willing to give them a try. They do have their own peer2peer implementation in addition to sftp, but it&apos;s restricted to the same account. Pricing is $29.95 for windows/mac and then $39.95 for the linux cli. They also have a Linux/Windows server, but I think that&apos;s for their management solution.</p>
<h4 id="cloudberrybackup"><a href="https://www.cloudberrylab.com/backup.aspx">CloudBerry Backup</a></h4>
<p>No idea if they have a peer2peer solution or sftp support. For upgrades after the first year, it&apos;s 20% of the original price. The offer a free version but it doesn&apos;t allow for custom retention, scheduling, compression, or encryption. Pricing is $29.99 per computer, with a volume discount on linux computers at 2+ for $24.99.</p>
<h4 id="urbackup"><a href="https://www.urbackup.org/">UrBackup</a></h4>
<p>This product is an opensource client/server backup system. It looks like I&apos;d have to run the server somewhere and then configure the clients to backup there. In order to get block-level changes on windows a lices would been to be purchased at $17 per windows client. There may be a way to archive to Amazon Glacier via S3, but I&apos;m not entirely sure.</p>
<h4 id="cloudbacko"><a href="https://www.cloudbacko.com">CloudBacko</a></h4>
<p>They offer a free Home version that looks like it supports Windows and Mac. They also offer a free mobile version which backs up to Dropbox, Google Drive or OneDrive. They also offer a Lite version ($19 per install) that offers the ability (for $9) to do a cloud2cloud backup, e.g. backup dropbox or google drive. I think combined with the mobile version might be a good way to backup phones. The lite version also offers the ability to backup the full windows install instead of just the data. In order to get Linux Support (right now?) you need to purchase the pro version at $149 per install, in addition, Ubuntu is not listed as supported - only RHEL and CentOS.</p>
<h4 id="duplicati"><a href="https://www.duplicati.com/">duplicati</a></h4>
<p>(added after initial post). Not much info (very little documentation even!) on the site, LGPL, supports Windows, Mac and Linux. Writing in .Net. Supports S3, sftp and Backblaze B2.</p>
<h4 id="rclone"><a href="https://rclone.org/">rclone</a></h4>
<p>This isn&apos;t really a backup solution, but I&apos;m including it here because it&apos;d be a good way for me to backup things that don&apos;t change (music/videos)</p>
<p>Edit @22:00 because somebody pointed out I missed iDrive. Adding details here for completeness.</p>
<h4 id="idrive"><a href="https://www.idrive.com/">iDrive</a></h4>
<p>Windows and Mac are supported with their personal plan, which is definitely cheaper than Crashplan was if you had less than 5TB. In order to get linux support you&apos;ll need to switch to their business solution which can get very pricey as you go up in storage requirements.</p>
<p>Edit 8/23 1300:<br>
Apparently iDrive personal <a href="https://twitter.com/IDriveBackup/status/900415573506404352">does support linux</a> - I swear when I looked last night the Linux was not supported in personal. Guess I need to try them out as well. Lots to look at.</p>
<p>Edit: 8/26</p>
<h4 id="arq"><a href="https://www.arqbackup.com/">Arq</a></h4>
<p>Arq is another program that can use S3 or Backblaze B2 as it&apos;s storage. It&apos;s only Windows &amp; Mac. It costs $49.99/user or server.</p>
<h4 id="syncrify"><a href="http://web.synametrics.com/Syncrify.htm">Syncrify</a></h4>
<p>Syncrify appears to be a custom client/server backup solution which supports Windows Linux and Mac. Personal edition is free but doesn&apos;t support file versioning, nor encryption. Single Pro license is $49. discount after 5 licenses. Licenses are per client.</p>
<h4 id="buddybackup"><a href="http://www.buddybackup.com">BuddyBackup</a></h4>
<p>Looks like a P2P only backup. Free; only supports windows. Blog hasn&apos;t been updated since 2014.</p>
<h4 id="resilio"><a href="https://www.resilio.com/individuals/">Resilio</a></h4>
<p>Looks more like a dropbox like sync program vs backup. Supports windows, linux, mac. Home version is $59.99; Family version (5 users) is $99.99. Used to be BitTorrent Sync</p>
<h4 id="syncbackpro"><a href="https://www.2brightsparks.com/syncback/sbpro.html">SyncBackPro</a></h4>
<p>Windows only; $54.95. interface looks like ui hell.</p>
<h4 id="restic"><a href="https://restic.github.io">Restic</a></h4>
<p>Cross platform, cli only, open source, written in go.</p>
<h4 id="andawholelotmore">And a whole lot more</h4>
<p>I found <a href="https://github.com/restic/others">this list</a> written by the author(s) of restic. It mostly contains linux only software.. but it&apos;s definitely something I&apos;ll look at.</p>
<h3 id="backendservice">Backend Service</h3>
<p>One choice with all this is which service to use for storage. Primarily I&apos;m interested in archive type storage, so things like Amazon S3, Google Cloud Storage or Azure Storage are probably too pricey. Instead I&apos;m interested in things like Amazon Glacier, Azure Sttorage LRS Cool, or Google Cloud Storage Coldline.</p>
<p>A few new ones I found in similar price point are <a href="https://www.backblaze.com/b2/cloud-storage.html">Backblaze B2</a> and <a href="https://wasabi.com">Wasabi</a>. Unlike typical Cold Storage, both Backblaze B2 and Wasabi offer instant download instead of having to wait 2-4 hours for availability. Wasabi has cheaper storage at $0.0039/GB/Month (min 1024GB) vs Backblaze&apos;s $0.005/GB/Month (no min); but Backblaze B2 offers the first 1GB downloaded per day free, with other downloads at $0.02/GB while Wasabi is $0.04/GB download. The qBackup page has a decent <a href="https://www.qualeed.com/en/qbackup/cloud-storage-comparison/">comparison of cloud storage providers</a> though they don&apos;t list everything available.</p>
<p>(edit 22:00) Oracle also offers an <a href="https://cloud.oracle.com/en_US/storage/archive-storage/pricing">archive storage service</a> which looks to be pretty competitive with pricing at $0.001/GB/month but I&apos;m not sure the exact costs to get the data out (they have a retrieval and transfer price listed.. it may be $0.125/GB total for up to 10TB). They also have a small read/write fee for items less than 10MB of $0.05 per 1000 requests.. so that could increase the cost depending on how the backups are done.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[DEF CON 25 CTF Quals - insanity]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="overview">Overview</h1>
<p>Problem:</p>
<pre><code>Are you a chicken?
&lt;host&gt;:&lt;port&gt;
https://2017.notmalware.ru/90ac48d8e27c81628dd56a6e3926a18cd6a399c3/insanity.tar.bz2
</code></pre>
<p>Unlike my last write up -  I did a lot of the work in solving this challenge so this write up will be a bit more detailed. In this challenge</p>]]></description><link>https://www.r3dey3.com/def-con-25-ctf-quals-insanity/</link><guid isPermaLink="false">5ad628e9851f9800016ae787</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Sat, 13 May 2017 04:08:45 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="overview">Overview</h1>
<p>Problem:</p>
<pre><code>Are you a chicken?
&lt;host&gt;:&lt;port&gt;
https://2017.notmalware.ru/90ac48d8e27c81628dd56a6e3926a18cd6a399c3/insanity.tar.bz2
</code></pre>
<p>Unlike my last write up -  I did a lot of the work in solving this challenge so this write up will be a bit more detailed. In this challenge we were given a <a href="https://www.r3dey3.com/static/2017-dc_quals/insanity.tar.xz">tar.bz2</a> (that was really an xz compressed file). This file contained an x64 binary (insanity) and 2 shared objects (libpocketsphinx.so.3 and libsphinxbase.so.3).</p>
<p>I started by searching for pocketsphinx to get an idea of what the shared library implements and quickly discovered the <a href="https://github.com/cmusphinx/pocketsphinx">github</a> page indicating that it does speech recognition. This tells me that at some point I will most likely need to send an audio file to the service to do something.</p>
<h1 id="model">model</h1>
<p>The first step was getting the program to run more than printing an error <code>Failed to create recognizer, see log for details</code>. Of course there&apos;s no log, but looking at the git repo for <a href="https://github.com/cmusphinx/pocketsphinx">pocketsphinx</a> and the code</p>
<pre><code class="language-c">  v4 = cmd_ln_init(
         0LL,
         v3,
         1LL,
         &quot;-hmm&quot;,
         &quot;./model/en-us&quot;,
         &quot;-lm&quot;,
         &quot;./model/en-us.lm.bin&quot;,
         &quot;-dict&quot;,
         &quot;./model/cmudict-en-us.dict&quot;,
         0LL);
</code></pre>
<p>shows that I need some sort of model files. Luckily the git repo has the files that worked. Doing a <code>ln -s pocketsphinx/model/en-us/ model</code> fixes the problem and lets the program start.</p>
<h1 id="audio">Audio</h1>
<p>The next step was to get some audio to feed into the program and determine the proper format. I searched for some text 2 speech websites and found <a href="http://www.text2speech.net">http://www.text2speech.net</a> that I was able to use to create some audio mp3s (the site has changed format a bit since the competition, previously you could set volume level and voice).</p>
<h2 id="preprocessing">pre-processing</h2>
<p>The next step was getting the file into the application. A 4 byte length is read, then that amount of data is read and fed into inflate - so the data is compressed with zlib. The next step is to figure out what a block of simd instructions was doing:</p>
<pre><code class="language-c">*((_QWORD *)&amp;v63 + 1) = 0x8000800080008000LL;
*(_QWORD *)&amp;v63 = 0x8000800080008000LL;
v15 = _mm_stream_load_si128((__m128i *)&amp;v63);
do
{
	v16 = _mm_stream_load_si128(v12);
	v17 = _mm_stream_load_si128(v12 + 1);
	_mm_stream_si128(v13, _mm_xor_si128(_mm_unpacklo_epi8(0LL, v16), v15));
	_mm_stream_si128(v13 + 1, _mm_xor_si128(_mm_unpackhi_epi8(0LL, v16), v15));
	_mm_stream_si128(v13 + 2, _mm_xor_si128(_mm_unpacklo_epi8(0LL, v17), v15));
	_mm_stream_si128(v13 + 3, _mm_xor_si128(_mm_unpackhi_epi8(0LL, v17), v15));
	v13 += 4;
	v12 += 2;
	--v14;
}
while ( v14 );
</code></pre>
<p>To do this, I set a breakpoint before this block of instructions and took a look at the input and then a breakpoint at the end, and compared the input to the output. Looking at the difference, an input of 0x41 0x42 0x43 0x44 was converted to 0x00 0xc1 0x00 0xc2 0x00 0xc3 0x00 0xc4. At first I just assumed looking at the xor value that it was only xoring with 0x8000, but it turns out it&apos;s taking an 8 bit value and essentially multiplying it by 256 (turning it into a 16 bit value) and then xoring it with 0x8000.</p>
<h2 id="speech2text">speech 2 text</h2>
<p>The next step was to figure out the correct format for the data. Looking at the <a href="http://cmusphinx.sourceforge.net/wiki/tutorialpocketsphinx">tutorial</a> we see that <code>it needs to be a single-channel (monaural), little-endian, unheadered 16-bit signed PCM audio file sampled at 16000 Hz.</code>  So the next step was converting it. Luckily linux has command line utilities for just about everything and a quick google search (or dozen) lead to the magic command line of:<br>
<code>ffmpeg -y -i &quot;$in&quot; -f s8 -acodec pcm_s8 -ar 16000 -ac 1 $out.raw</code> to convert an mp3 into a raw file with the correct format. I wish I could say that I immediately knew that I needed to do 8 bit because of the pre-processing done but there was a lot of trial and error in getting the correct format (including sending the sample files in the pocketphoenix repo)</p>
<h2 id="textprocessing">text processing</h2>
<p>The next step was to figure out what it was doing with the text processing:</p>
<pre><code class="language-c">insanity_count = 0;
input_idx = 0;
decoded_text = ps_get_hyp(v5, &amp;v61);
while ( *(_BYTE *)(decoded_text + input_idx) &amp;&amp; (unsigned int)(data_idx - 2) &lt;= 1000 )
{
	if ( !memcmp((const void *)(decoded_text + input_idx), &quot;insanity &quot;, 9uLL) )
	{
		++insanity_count;
		input_idx += 9;
	}
	else
	{
		if ( memcmp((const void *)(decoded_text + input_idx), &quot;insane&quot;, 7uLL) )
			goto reloop;
		v22 = insanity_count;
		input_idx += 7;
		insanity_count = 0;
		opcode_buf[data_idx++] = v22;
	}
}
</code></pre>
<p>as we can see it is counting the times the word insanity appears and then when the word insane appears it stores this count into some buffer. So the next step was putting together an audio file of <a href="https://www.r3dey3.com/static/2017-dc_quals/insanity.raw">insanity</a> and <a href="https://www.r3dey3.com/static/2017-dc_quals/insane.raw">insane</a>. Luckily with the help of that text2speech website and ffmpeg getting the speech2text for a single word went pretty quick. The next step was putting together a &quot;sentence&quot; that would properly decode.</p>
<p>Luckily silence is a simple as adding a bunch of zeros into the input stream so adding a pause was very simple: we just had to add some zeros between the words. knowing that the sample rate was 16000 hz, adding 4000 zeros would be a 1/4 second pause and that was plenty for the library to recognize distinct words.</p>
<h1 id="muchinsanity">much insanity</h1>
<p>The next problem came when trying to add more than a few &apos;insanity&apos;s. The library would mess up and change an insanity to &apos;been to too&apos; or some other nonsense. Looking at the code, the initial buffer read size of compressed data was limited to 64k chunks, but we weren&apos;t hitting that - after all, a 4000 zeros compressed really well, we were barely at 16k. So the next step was looking at how the data is decompressed.<br>
Looking at the decompression buffer, it turns out that inflate is given a 64k buffer (aka 4 seconds worth of samples) to decompress into. That buffer is fed to the speech to text; and then inflate is called again, and then the next chunk of decompressed data is it fed to speech2text and so on. So after a bit of thought I reasoned that when the speech2text is fed part of a word in one round and then part the next it doesn&apos;t process it correctly.</p>
<p>So first I tried padding out the silence (&apos;\x00&apos;) between &apos;insanity&apos;s to make sure that 3 would fit in a single 64k buffer (so ~1/3 a second between words as the word was slightly longer than a second).. This got me further but it would still mess up at around 8 or so.<br>
Then I took a look at the hexdump of the insanity raw file.</p>
<pre><code>00000000  00 ff ff 00 00 ff 00 00  00 00 ff ff 00 00 00 ff  |................|
00000010  00 00 00 ff 00 ff 00 00  00 ff 00 00 00 00 00 00  |................|
</code></pre>
<p>and I see that it starts with a <code>\x00</code> ... so I started thinking, i wonder if the zlib is including that first <code>\x00</code> in with the silence and not extracting the ending silence in a block because that <code>\x00</code> doesn&apos;t fit in the buffer (since I was padding the decompressed data to exactly 64k).</p>
<p>I tried changing the amount of silence and the value used  to &apos;\x01&apos; and between words to &apos;\x03&apos; and that worked; I could successfully send a sentence with a whole bunch (i think i tried 80) &apos;insanity&apos;s.</p>
<h1 id="imgoinginsane">I&apos;m going insane</h1>
<p>So now we can decode a single sentence and store a byte into what I eventually called the <code>opcode_buf</code>. The code would continue to read a length and audio data, decode and store a byte until a length of 0 was sent at which point it would go to the emulator portion.</p>
<h1 id="emulator">Emulator</h1>
<p>The <code>opcode_buf</code> consisted of an array of qwords, with the first 2 initialized; index 0 was set to the address of the <code>opcode_buf</code> (or&apos;d with <code>0x8000000000000000</code>) and index 1 was set to the last decoded text (or&apos;d with the same value). And then the values stored with insanity/insane-ness were added starting at index 2.</p>
<p>Looking at the operations it was easy to see that when the high bit is set, the value is treated as a pointer or string, and when it&apos;s not set it&apos;s treated as a numeric value (this also means no negatives with math).</p>
<p>I was quickly able to identify the operations:</p>
<ul>
<li>0 - exit</li>
<li>1 - push value</li>
<li>2 - add or strcat</li>
<li>3 - subtract (numbers only)</li>
<li>4 - multiply (numbers only)</li>
<li>5 - divide</li>
<li>6 - load</li>
<li>7 - store</li>
<li>8 - jump (if nonzero)</li>
<li>9 - convert numeric to string (single byte only)</li>
<li>other - push value = (op_code - 10)</li>
</ul>
<p>The <code>pc</code> started at index 2 - the first value stored using the speech 2 text. and the data stack started at 1 greater than index of last value stored (a 0 was pushed on in that position). This meant that depending on the operations you could get the <code>pc</code> and data_index to cross.</p>
<p>Every operation that used data values would &apos;pop&apos; them off, then push the result.</p>
<h1 id="easiercode">Easier Code</h1>
<p>The first thing I noticed is that the jump instruction did not validate that the target was within the 1000 qword opcode buf.. this meant that we could jump to other data... and since almost everything (compressed &amp; uncompressed buffers and opcode_buf) were stored on the stack we could jump to data we sent without having to do the speech2text for everything.</p>
<p>The first step was to figure out how to get data onto the stack without inflate failing (which causes the program to bail) and the speech2text to return something valid (but not necessarily insanity/insane) as when it failed it returned NULL and the program crashed.</p>
<p>I settled on sending the word <a href="https://www.r3dey3.com/static/2017-dc_quals/no.raw">no</a> followed by the data I wanted to send. When the speech2text decoded no, and it was checked for insanity/insane the program would just go back to the read length part and as long as I sent 0, the extra data would still be in the decompression buffer on the stack.</p>
<p>So now that I knew how to get data onto the stack the next step was getting the emulator to jump to that location. I figured out how far <code>opcode_buf</code> was from the uncompress buffer (not the xor masked buffer.. because I didn&apos;t want every other byte to be 0) using gdb. It turned out I needed a jump of over 128k bytes to just get to the start of the decompress buffer, then some to get over the &apos;no&apos; audio. So I needed to figure out how to get a really large value in the data stack to use as a jump target.</p>
<p>Luckily we have a multiply instruction and doing some root calculations and guessing, we determined that <code>11*11*12*13</code> would get us far enough into the decompress buffer to get past the no.</p>
<p>So the instruction sequence to get opcodes to execute in the decompress buffer instead of the opcode buffer (so we can use larger values, and less insanity) turned out to be: (remember we had to send this with the multiple &apos;insanity&apos;s and a single insane audio to get the value we wanted)</p>
<ul>
<li>add (2)</li>
<li>mult (4)</li>
<li>mult (4)</li>
<li>mult (4)</li>
<li>mult (4)</li>
<li>jmp (8)</li>
<li>1 #truth value for jmp</li>
<li>13</li>
<li>12</li>
<li>11</li>
<li>11</li>
</ul>
<p>The add instruction was necessary because after finishing reading a 0 was pushed onto the stack as the last data value and multiple would just cause 0&apos;s to propagate up.</p>
<p>This sequence would cause the <code>pc</code> to be set to 18883, which was 11976 bytes into the decompressed buffer (1896 bytes larger than the no.raw). Which was perfect.</p>
<h1 id="ripcontrol">rip control</h1>
<p>Now that I could store large values it was time to figure out how to get execution. We quickly realized that the load and store operations also did not check bounds.</p>
<p>The store operation would load a value at a specific index in <code>opcode_buf</code>, the index and value were pulled from the data stack and as long as the index wasn&apos;t negative it would store the value at <code>opcode_buf[index]</code>. This allowed us to have a very simple stack overwrite with whatever we wanted. Given that we knew the relative location of <code>opcode_buf</code> to the return address (<code>-0x41f98 *8</code> bytes) it was simple to overwrite the return address.<br>
Load worked slightly differently, it actually took a parameter and a data value. The parameter could be either 0 or 1, 0 to load from the opcode buf, and 1 to load from the decoded text. Technically, it used the address stored in index 0 or 1 of the opcode buf. This address had to have the high bit set as if it was a string.<br>
With this load we could read the return address (same offset as before), and then do emulator calculations to figure things out.</p>
<h1 id="dripdripdripleakingdataslowly">drip drip drip - leaking data slowly</h1>
<p>Since the entire program was written inside of main, the return address was that of the call to main inside <code>__libc_start_main</code>. We need to leak some addresses in order to determine which libc was in use. Luckily the program printed the top value on the data stack (current item) when the exit instruction was used; if the high bit was set it printed a string, otherwise it printed the value in hex.</p>
<p>Leaking the <code>__libc_start_main</code> return was easy, we just had to load the return address into current data item and exit. However this address wasn&apos;t quite enough to get use an exact libc match. In order to leak other addresses finding the GOT would be most helpful. Luckily main calls other things and the return address inside of main is available. And it just so happens there is one call that happens every time before the emulator is run.</p>
<p>Knowing the offset of the bottom of main&apos;s stack frame to <code>opcode_buf</code> we can figure out that what index (-29) we need to load (which didn&apos;t have negative or positive bounds checks!). Loading this gave us the actual return address pushed by the call to write at 0x1369 in main(). We could then add the offset to the appropriate entry in the got to get the actual address. We couldn&apos;t just store this address in offset 0 of <code>opcode_buf</code> because it didn&apos;t have the high bit set and that would cause a subsequent load operation to fail (due to checks).</p>
<p>Since setting the high bit with an or operation is the same as adding the same value (since we know the high bit isn&apos;t set) we can use the add operations... however we cannot just add 0x800000000000000 as that is a negative number and add cannot be used. instead we first add 0x101 and then add 0x7ffffffffffffeff. The 0x100 is to account for any oddities that could arise with the push_value instruction (which I don&apos;t think there are any after looking at the code again during this write up).</p>
<p>The final trick was storing the value in index 0 and then doing another load operation to read the value and exiting.</p>
<h1 id="system">system()</h1>
<p>So now that we knew addresses of a few glibc functions we could look for the bin/sh single instruction gadget in libc. However after talking with some teammates they mentioned that this would not work because sh was busybox and it requires argv[] to be set... so plan 2.</p>
<p>Since we had libc, and knew were system was, and we can find the &quot;/bin/sh&quot; string, all I needed to do was load the address of &quot;/bin/sh&quot; string into rdi and call system. So I found a pop rdi gadget at 0x22b1a in libc, and the bin_sh string at 0x17ccdb, with system() at 0x46640. Now we could use those addresses as well as the address of the call main in <code>__libc_start_main</code> (0x21ec5) to write some emulator instructions to overwrite the stack.</p>
<p>The full chain is a little annoying, but it basically broke down into the following steps:</p>
<ul>
<li>Load main&apos;s return address (<code>__libc_start_main</code>)</li>
<li>Add the offset for system</li>
<li>store the value at main&apos;s return rsp + 0x10</li>
<li>Load main&apos;s return address (<code>__libc_start_main</code>)</li>
<li>Add the offset for &quot;/bin/sh&quot;</li>
<li>store the value at main&apos;s return rsp + 0x8</li>
<li>Load main&apos;s return address (<code>__libc_start_main</code>)</li>
<li>Add the offset for pop rdi gadget</li>
<li>store the value at main&apos;s return rsp</li>
<li>exit instruction</li>
</ul>
<p>The hardest part for us was finding the correct libc. Even when we found it, for some reason (not sure why) I couldn&apos;t run the program locally with that libc. But the address worked and we were able to capture the flag. (sorry I didn&apos;t save what it was)</p>
<p>Files:</p>
<ul>
<li><a href="https://www.r3dey3.com/static/2017-dc_quals/insanity_solve.py">Full python script</a></li>
<li><a href="https://www.r3dey3.com/static/2017-dc_quals/insanity_libc.so.6">libc</a></li>
<li><a href="https://www.r3dey3.com/static/2017-dc_quals/insanity.tar.xz">challenge tar</a></li>
<li><a href="https://www.r3dey3.com/static/2017-dc_quals/insanity.raw">insanity.raw</a></li>
<li><a href="https://www.r3dey3.com/static/2017-dc_quals/insane.raw">insane.raw</a></li>
<li><a href="https://www.r3dey3.com/static/2017-dc_quals/no.raw">no.raw</a></li>
</ul>
<h1 id="otherbugs">Other Bugs</h1>
<p>I&apos;m just going to list the various other bugs found in the emulator as there were quite a few.</p>
<ul>
<li>The strcat operation set the high bit on the result (no longer an address type)</li>
<li>The strcat operation will free a value even if it wasn&apos;t necessarily malloc&apos;d</li>
<li>The push value would allow pushing of an address</li>
</ul>
<p>These are probably not useful with a one-shot chance through the emulator.. but ya never know.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[DEF CON 25 CTF Quals - reeses revenge]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="overview">Overview</h1>
<p>This problem is a rehash of the reeses problem from DEF CON 21 CTF Finals. In this case the problem is compiled for x64 instead of ARM.  We were provided with <a href="https://www.r3dey3.com/static/2017-dc_quals/reeses.tgz">a binary and 4 sample files</a>.</p>
<p>Let me start by saying that I only had a small part</p>]]></description><link>https://www.r3dey3.com/def-con-25-ctf-quals-reeses-revenge/</link><guid isPermaLink="false">5ad628e9851f9800016ae786</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Sat, 06 May 2017 01:19:37 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="overview">Overview</h1>
<p>This problem is a rehash of the reeses problem from DEF CON 21 CTF Finals. In this case the problem is compiled for x64 instead of ARM.  We were provided with <a href="https://www.r3dey3.com/static/2017-dc_quals/reeses.tgz">a binary and 4 sample files</a>.</p>
<p>Let me start by saying that I only had a small part in solving this problem during the competition and my teammates did a huge majority of the work. I vaguely remember this problem from DEF CON 21 CTF, and back then I think that I may have identified it was an MIPS emulator, but we were never able to get execution (MIPS nor ARM).</p>
<p>The problem starts by reading a 4 byte length and then a buffer of that size, as long as it is less than 100,000. This buffer is then processed as a custom executable file format which includes an RSA signature. Not having the private key means that the only binaries that can be loaded are the 4 sample programs included with the challenge.</p>
<h2 id="fileformat">File format</h2>
<p>The file format is rather simple with a structure similar to an elf header with a count and offsets of the number of sections and number of register initializations.</p>
<pre><code class="language-c">struct file_header {
   uint32_t unk1;
   uint32_t unk2;
   uint32_t unk3;
   uint32_t section_info_offset;
   uint32_t reg_init_info_offset;
   uint16_t num_sections;
   uint16_t num_reg_init;
   uint32_t sig_offset;
   uint32_t entry;
}
</code></pre>
<p>The header had the following validations:</p>
<ul>
<li>sig_offset had to be file_size - 256.</li>
<li>a max of 100 sections</li>
<li>a max of 33 reg inits</li>
<li>each section info was 20 bytes</li>
<li>each reg init was 8 bytes</li>
</ul>
<p>The sections headers were fairly simple:</p>
<pre><code class="language-c">struct section_info {
   uint32_t load_addr;
   uint32_t unk;
   uint32_t length;
   uint32_t offset;
   uint32_t unk1;
}
</code></pre>
<p>And the register initialization was even simpler:</p>
<pre><code class="language-c">struct reg_init_info {
   uint8_t reg_num;
   uint8_t pad[3]
   uint32_t value;
}
</code></pre>
<p>Even though the file header has an entry, the emulator actually used register &apos;32&apos; as the entry (this doesn&apos;t matter because the samples had both values equal).  One of my teammates took the time to write a <a href="https://www.r3dey3.com/static/2017-dc_quals/reeses_loader.py">loader script</a> for IDA to be able to load programs with this file format.</p>
<h1 id="mips">MIPS</h1>
<p>The emulator handled a few system calls:</p>
<ul>
<li>Read</li>
<li>Write</li>
<li>Malloc</li>
<li>Time</li>
<li>Rand</li>
<li>Exit</li>
</ul>
<p>Read and write were restricted to stdin and stdout respectively; and due to the lack of open this meant that not only would we need to get MIPS code execution, we would need to find a vulnerability in the emulator to get x64 code execution.</p>
<p>The problem included 4 sample programs. Each was signed appropriately to be loaded into the emulator. My teammates started by looking at sample1, which was lucky because sample1 is the one with the vulnerability that enables MIPS code execution. I quickly identified what the other 3 samples were doing while writing this (for completeness)</p>
<ul>
<li>sample1 - compression/decompression</li>
<li>sample2 - echo service</li>
<li>sample3 - encrypt/decrypt service</li>
<li>sample4 - sha256 service</li>
</ul>
<h2 id="sample1">Sample1</h2>
<p>Sample1 reads a single byte for the operation type and then a 4 byte length. The length must be less than 0x4001. After reversing it for a while sample1 was identified as performing compression or decompression based on the operation (0 or 1 respectively).<br>
The compression algorithm was identified as lzss, however it did not use the standard parameters - EI was 13 and EJ was 5. My teammates quickly modified a version of <a href="https://www.r3dey3.com/static/2017-dc_quals/lzss.c">lzss.c</a> they were able to find to have the adjusted parameters.</p>
<p>I&apos;m not sure if testing or reverse engineering lead to the realization that the uncompress operation does not properly bounds check. My teammates were able to identify that the uncompress buffer would eventual run into the current stack area enabling an overwrite of the saved ra value, so that when the uncompress function returns we would have control of the pc.</p>
<p>It turned out that the offset into the uncompressed buffer for this saved ra was 0x25edc. As long as the payload would compress to less than 16k, we were able to control MIPS execution. They were also able to identify that the buffer is uncompressed to 0x40a0b8, and due to the lack of ASLR and NX, we could include our MIPS shellcode at the start of the buffer and return to it.</p>
<h1 id="x64control">X64 control</h1>
<p>So now that we had control of the MIPS execution environment, the next step was to get control in x64 context.</p>
<p>One of my teammates identified that the the <code>Halt and Spontaneously Combust</code> instruction had a s64 simple stack overflow when executed in the branch delay slot. It would copy the registers onto the stack overflowing the return address. The exact opcode for the instruction had to be 0xcfe00000 in order for the overflow to occur. In addition in order for the exception handler to not exit, register $20 had to be 100 so that when copied the parameter passed would cause the handler to process it as an unknown exception.</p>
<h2 id="wheretogo">Where to go?</h2>
<p>Now that we can control rip, the question lies as to where to point it. reeses_revenge was compiled with full PIE and NX, and ASLR is enabled, meaning there are no known fixed addresses and a memory leak or other known address is needed.<br>
This is the part where I started helping.. and sadly it took me far to long to finish. I think I looked at the implementation of every MIPS instruction in the code at least 3 times. My teammates also identified a bug in the system call instruction in that it was possible to use a negative index into the system call table - system calls were 4000 through 4015, but the check for range was val-4000 &lt; 15 and it was a signed check. So system calls less that 4000 would use other memory locations for the information. I tried looking at all possible combinations of using that to leak information, but due to differences in how the system calls were done compared to instructions this proved useless.<br>
I then investigated the coprocessor instructions. After reversing the two supported instructions I was able to determine that they implemented rc4, with one being the set key operation and the other being encrypt/decrypt. It turned out that the encrypt/decrypt could be called without calling the set key one, and it would use unitialized memory as the keystate, but the values leaked were not very helpful as it wasn&apos;t the full value of any addresses as the rc4 key state is only byte values.</p>
<p>Eventually I looked at the malloc system call again and realized that not only did it allocate an RWX page, it also used the internal random function to generate the address. So the next step was to figure out if we could predict the value returned by random. This is eventually what lead us to success.</p>
<pre><code class="language-c">allocate_page() { //0x4b60
  ...
  v8 = do_rand();
  v9 = mmap((void *)(((unsigned __int64)v8 &lt;&lt; 12) | 0x400000000000LL), 0x1000uLL, 7, 50, -1, 0LL);
  ...
}
</code></pre>
<p>In order to predict the value for rand we need send some rand values back from our MIPS code:</p>
<pre><code class="language-asm">.set noreorder
main:
# assemble with mips-linux-gnu-as -O0 --EL -o mips_sc.elf mips_sc.asm ; mips-linux-gnu-objcopy -O binary -j .text mips_sc.elf mips_sc.bin; mips-linux-gnu-objdump -d mips_sc.elf;

#ra contains the address of main
	add $s7, $ra,0

leak_data:
	add $s1, $s7, 0x1000
#time systemcall
	li $v0, 4013
	syscall
	sw  $v0, 0($s1)
	add $s1, 4


#leak 0x10 RAND values
	li $s2, 0x10
rand_again:
	li $v0, 4005
	syscall
	sw  $v0, 0($s1)
	add $s1, 4
	sub $s2, 1
	bne $s2, 0, rand_again
	nop

#WRITE leak
	li $v0, 4004
	li $a0, 1
	add $a1, $s7, 0x1000
	li $a2, 68
	syscall

</code></pre>
<p>Once we had the rand values we needed to both determine the rand algorithm and the seed value used. Reversing the algorithm was pretty easy, and I implemented it in <a href="https://www.r3dey3.com/static/2017-dc_quals/reeses_rand.py">python</a>. The seed calculation was pretty simple to find as well.</p>
<pre><code class="language-c">main() {
  ...
  v4 = time(0LL);
  srand(((unsigned __int64)&amp;printf &gt;&gt; 12) ^ v4); //0x54c2
  ...
</code></pre>
<p>One thing to note is that even though the address is treated as a 64 bit value, srand only uses 32 bits for the seed. At first I missed the shift right operation and thought that because the bottom 12 bits are not randomized and that because we can get the time it will be pretty simple to brute force the entire randomized space (20 bits). However when trying this I realized there was the shift 12... oops.</p>
<p>When looking at ALSR addressed of printf with the shift 12, it&apos;s usually 0xfxxxxxx or 0xexxxxxx with a high probability (in my testing) of 0xfxxxxxxx. And then when looking at the current unix time, it&apos;s around 0x59xxxxx, so combining these two things the seed is likely to be between 0xa0000000 and 0xafffffff.</p>
<p>Instead of just searching the space, which we would not have enough time to due to alarm(), I used random.randint to just try various seeds, and then would compare the first four values against what was leaked. . If they matched, the 17th random value would be calculated, and the same operations in malloc_page would be done (val &lt;&lt;12 | 0x400000000000) and then this value as well as the length of our x64 shellcode would be sent to the MIPS shellcode.</p>
<p>The MIPS shellcode would read those values, allocate a page of memory, and read the x64 shellcode into that newly allocated page, which thanks to the rand calculations we know the address of. The MIPS shellcode would then setup the x64 stack overwrite to return to that known address and perform the overwrite which would then give our x64 shellcode execution. Simple /bin/sh shellcode was used.</p>
<p>Because the brute force was a random try, I just ran the script in a loop until it found a successful match.</p>
<p><a href="https://www.r3dey3.com/static/2017-dc_quals/reeses_solve.py">Full python script</a></p>
<p><a href="https://www.r3dey3.com/static/2017-dc_quals/reeses_mips_sc.asm">Full mips shellcode</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Honeynet Project - Forensics challenge 14 - Weird Python]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>This is my writeup for the Honeynet Project - <a href="http://honeynet.org/node/1220">Forensics challenge 14 - Weird Python</a> there were multiple SSL and HTTP connections.</p>
<p>I initially opened the pcapng in Wireshark and saw that there were multiple SSL and HTTP connections. Rather than combing through wireshark looking at each one I went</p>]]></description><link>https://www.r3dey3.com/2015-04-honeynet-14-weird-python/</link><guid isPermaLink="false">5ad628e9851f9800016ae785</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Mon, 20 Apr 2015 05:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>This is my writeup for the Honeynet Project - <a href="http://honeynet.org/node/1220">Forensics challenge 14 - Weird Python</a> there were multiple SSL and HTTP connections.</p>
<p>I initially opened the pcapng in Wireshark and saw that there were multiple SSL and HTTP connections. Rather than combing through wireshark looking at each one I went investigating tools that would analyze HTTP traffic from a PCAP.<br>
I stumbled on <a href="https://pcapperf.appspot.com/">pcapperf</a> - a pretty nice web based analyzier. It shows <a href="https://pcapperf.appspot.com/view?hash_str=5349ea30533d7fbdc03257d27e301ed8">results</a> similar to the network tab in chrome&apos;s inspect interface. The site does not operate on pcapng format, so I converted it to pcap using wireshark&apos;s save feature.</p>
<p>Using this I was able to see the various sites visited, and also the method the attacker used (Questions 1, 2, 3, 5). Using wireshark I extracted the downloaded game from the fake website.</p>
<p>Answers to the various questions follow.</p>
<!-- more -->
<h6 id="1byodseemstobeaveryinterestingtopicwhatdidyourbossdoduringtheconference">1) BYOD seems to be a very interesting topic. What did your boss do during the conference?</h6>
<ul>
<li>Visited Google.fr and Google+</li>
<li>Reddit.com</li>
<li>Searched reddit for &quot;byod&quot;</li>
<li>9gag.com</li>
<li>thewayoftheninja.org   -&gt; to download n</li>
</ul>
<p>Links followed:</p>
<ul>
<li><a href="http://www.reddit.com/r/talesfromtechsupport/comments/2i46ss/satans_cpa_did_sign_the_byod_policy_from_hr/"><code>http://www.reddit.com/r/talesfromtechsupport/comments/2i46ss/satans_cpa_did_sign_the_byod_policy_from_hr/</code></a></li>
<li><a href="http://www.reddit.com/r/sysadmin/comments/1ue8qd/for_all_you_powershell_fans_nice_blog_about_using/"><code>http://www.reddit.com/r/sysadmin/comments/1ue8qd/for_all_you_powershell_fans_nice_blog_about_using/</code></a></li>
</ul>
<h6 id="2whatmethoddidtheattackerusetoinfectyourbosswhichsystemsieipaddressesareinvolved">2) What method did the attacker use to infect your boss? Which systems (i.e. IP addresses) are involved?</h6>
<p>Spoof&apos;d the DNS response for &quot;www.harveycartel.org&quot; to be 81.166.122.238<br>
ninja-game.org also resolves to this IP</p>
<h6 id="3basedonthepcapwhichfileswereexfiltratedlistthefilenames">3) Based on the PCAP, which files were exfiltrated? List the filenames.</h6>
<ul>
<li>C:\Users\admin\Desktop\sensitive+documents.doc</li>
<li>C:\Users\admin\Desktop\Tools\odbg201\help.pdf</li>
<li>C:\Users\admin\Documents\private\affair\holiday\EmiratesETicket1.pdf</li>
<li>C:\Users\admin\Documents\private\affair\holiday\EmiratesETicket2.pdf</li>
</ul>
<p>Exfiled to <a href="http://ninja-game.org/submit_highscore">http://ninja-game.org/submit_highscore</a></p>
<p>Using a combination of wireshark and <a href="https://pcapperf.appspot.com/view?hash_str=5349ea30533d7fbdc03257d27e301ed8">https://pcapperf.appspot.com/view?hash_str=5349ea30533d7fbdc03257d27e301ed8</a></p>
<h6 id="4canyousketchanoverviewofthegeneralactionsperformedbythemalware">4) Can you sketch an overview of the general actions performed by the malware?</h6>
<p>The initial download pretends to be the game the user downloaded. It&apos;s a self extracting rar that does 2 things</p>
<ul>
<li>Runs the python dropper main.pyc</li>
<li>Runs an older version of the game</li>
</ul>
<p>The dropper retrieves a payload which then exfils all *.pdf, *.doc, *.docx, *.xls, and *.xlsx files in the current user&apos;s home directory.</p>
<p>Used:<br>
Python source<br>
IDA Pro<br>
unwind - <a href="https://github.com/evanw/unwind">https://github.com/evanw/unwind</a><br>
uncompile 2 - <a href="https://github.com/wibiti/uncompyle2">https://github.com/wibiti/uncompyle2</a></p>
<p>Modified unwind to take into account the modifications that were made to the python&apos;s marshaling code.</p>
<h6 id="5doyouthinkthisisatargetedoranautomatedattackwhy">5) Do you think this is a targeted or an automated attack? Why?</h6>
<ol start="5">
<li>Targeted to visitors who download the game; an older version of the game was included, not the one download.</li>
</ol>
<h6 id="6themalwareseemstobewritteninpythonisthisnormalpythonwhatsdifferent">6) The malware seems to be written in Python. Is this &quot;normal&quot; Python? What&apos;s different?</h6>
<p>It&apos;s fairly normal.. once you get past the bytecode obfuscation.</p>
<p>-- All code objects had a fake 226 byte code object:</p>
<pre><code class="language-language-python">import sys
sys.exit(&apos;\r\ndebugger detected.\r\nsignature: 233f3f3b7164642c2424652c276431723a7d021e&apos;)
</code></pre>
<p>added to stop debugging/reversing without using the embedded python interpreter</p>
<p>Also, all string objects (which included the bytecode) were masked with a rolling xor pad.</p>
<pre><code class="language-language-python">i = len(s) - 1
cur = 43
while i &gt;= 0
  s[i] = s[i] ^ cur
  cur++
  i--
</code></pre>
<h6 id="7whatdoesmainpycdobonuscanyouprovideadecompiledversion">7) What does main.pyc do? (Bonus: Can you provide a decompiled version?)</h6>
<p>It reads the USERNAME environment variable, and makes a request to <a href="http://ninja-game.org/highscores?%7BUSERNAME">http://ninja-game.org/highscores?{USERNAME</a>} to retrieve the main payload.</p>
<p>The main payload is masked using some algorithm</p>
<p>{% include_code lang:python weird_python/dropper_main.py %}</p>
<h6 id="8howisthefinalpayloadprotectedhowisitdecryptedbythedropperbonuscanyouprovideadecompiledversion">8) How is the final payload protected? How is it decrypted by the dropper? (Bonus: Can you provide a decompiled version?)</h6>
<p>{% include_code lang:python weird_python/payload.py %}</p>
<p>The final payload in protected with a simple substitution cipher.</p>
<h6 id="9whydidpeteleavethecompany">9) Why did Pete leave the company?</h6>
<p>His wife has a ticket on the same flights as the boss</p>
<h6 id="10yourbossmentionedhesgoingtothehoneynetworkshopinstavangerbutyourenotallowedtojoinhimwhyso">10) Your boss mentioned he&apos;s going to the Honeynet Workshop in Stavanger, but you&apos;re not allowed to join him. Why so?</h6>
<p>He&apos;s actually going to Dubai</p>
<h6 id="11bonustherearefivesuperheroeshiddeninthechallengewhichofthemdidyoufind">11) Bonus: There are five superheroes hidden in the challenge. Which of them did you find?</h6>
<h6 id="12optionalpleaseprovidesomefeedbackonthechallengewhatdidyoulikedislike">12) Optional: Please provide some feedback on the challenge! What did you like/dislike?</h6>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Choosing sync/cloud software]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>There&apos;s a few new computers in my circle of family - my parents just bought one and my wife&apos;s laptop and phone - and I need a better solution for backing up everything.</p>
<p>My previous solution <a href="%7B/2010/02/cftbackup-intro/">CFTBackup</a> was no longer working for windows computers as they</p>]]></description><link>https://www.r3dey3.com/2015-03-choosing-sync-cloud-software/</link><guid isPermaLink="false">5ad628e9851f9800016ae784</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Thu, 05 Mar 2015 22:33:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>There&apos;s a few new computers in my circle of family - my parents just bought one and my wife&apos;s laptop and phone - and I need a better solution for backing up everything.</p>
<p>My previous solution <a href="%7B/2010/02/cftbackup-intro/">CFTBackup</a> was no longer working for windows computers as they were reinstalled or replaced. And I never got the whole part of the offline sync working; plus after using a simple rsync for almost 4 years, I&apos;ve determined that the 150Kbit/s limit was more than adequate to back things up in a timely fasion and a lot less hastle.</p>
<p>So it&apos;s time for a new solution. I recently bought two new <a href="http://www.amazon.com/gp/product/B00HHAJRU0/ref=ox_sc_sfl_title_1?ie=UTF8&amp;psc=1&amp;smid=ATVPDKIKX0DER">HGST Deskstar NAS 4TB</a> hard drives as space was starting to get full on my 1.5TB (at my house) and 1TB (my parents house) drive&apos;s.</p>
<p>For refresher the hardware the drive is going into:</p>
<ul>
<li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16813121399">Intel BOXD510MO</a> - An Intel Atom based board; populated with 2GB RAM</li>
<li><a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16811154091">Mini ITX Case</a></li>
</ul>
<p>Now I needed to find a better solution to sync the two backup systems and backup the files off the desired systems.</p>
<!-- more -->
<h3 id="requirements">Requirements</h3>
<ul>
<li>Files are stored on the backup system in the same hierachy as on the target systems. I don&apos;t want to be tied to a particular software platform. This means no binary blobs of random names.</li>
<li>Client should exist for Windows and Linux (at a minimum) and preferably Android
<ul>
<li>Automatic startup on windows and linux</li>
<li>Ease of use</li>
</ul>
</li>
<li>I shouldn&apos;t need to have a copy of everything everwhere. E.g. I don&apos;t need my parents data on my laptop.</li>
<li>The solution should support some form of versioning so that I can restore an older version of a file (up to some point in time)</li>
<li>Some level of access control; not necesarily by username/password</li>
<li>Ability to have multiple &quot;servers&quot; with copies of the data. I should be able to configure it so that files are only sync&apos;d to one location if I desire.</li>
<li>&quot;Headless&quot; mode as a full feature. Not some hacky solution</li>
<li>Ability to handle 350,000 files; approx 1TB right now.</li>
<li>Free</li>
<li>Preferably open source</li>
</ul>
<p>Things it doesn&apos;t need:</p>
<ul>
<li>Enterprise level number of users</li>
<li>Git integration</li>
<li>Cloud based backup</li>
</ul>
<p>Other things that would be nice</p>
<ul>
<li>Ability to share a file publicly</li>
<li>Ability to have a append only backup
<ul>
<li>E.g. I pull pictures from my camera onto my laptop, once they are backed up and I&apos;m done with them, I want to delete them from my laptop, but have them still be on the server.</li>
</ul>
</li>
</ul>
<h2 id="theproducts">The Products</h2>
<p>I&apos;ve basically found three categories of products so far:</p>
<ul>
<li>Cloud Backup Solutions</li>
<li>Cloud Storage Solutions - (think DropBox)</li>
<li>P2P Sync Solution</li>
</ul>
<h3 id="cloudbackupsolutions">Cloud Backup Solutions</h3>
<p>The only product in this category that I found with a linux client was <a href="https://www.code42.com/crashplan/">CrashPlan</a>.</p>
<h4 id="crashplan">Crashplan</h4>
<p>Pros:</p>
<ul>
<li>Easy setup</li>
<li>Has Windows, Linux &amp; Android Clients</li>
<li>Easy setup, ability to share space with not just yourself, but friends</li>
<li>Cloud backup option</li>
<li>Not tested, but you can have multiple backup locations</li>
<li>Has versioning, but limited to Week old, 90 day old, 1 year old, and 2 years old</li>
</ul>
<p>Cons:</p>
<ul>
<li>Requires java</li>
<li>The headless mode isn&apos;t supported, but is possible because it takes advantage of how the management is client/server</li>
<li>All backups are in a proprietary binary format</li>
<li>Not open source</li>
<li>Not real time backup (only backs up on interval)</li>
</ul>
<h3 id="cloudstoragesolutions">Cloud Storage Solutions</h3>
<p>I found a few in this category, along with some that are no longer maintained. One of the requirements for this category was that I need to be able to run my own server.</p>
<ul>
<li><a href="https://pyd.io/">Pydio</a></li>
<li><a href="https://owncloud.org/">OwnCloud</a></li>
<li><a href="http://seafile.com/en/home/">Seafile</a></li>
</ul>
<p>It turns out I didn&apos;t look at any of these solutions for the backup portion for the following reasons:</p>
<ul>
<li>Lack of multi-server support (with distint storage, not just load balancing with shared storage)</li>
<li>Data is stored in binary &quot;proprietary format&quot;</li>
<li>Poor performance reviews</li>
</ul>
<h3 id="p2psyncsolution">P2P Sync Solution</h3>
<p>This solution is closest to what I was using with my rsync setup. By definition it copies files in the same directory tree as the source.</p>
<ul>
<li><a href="https://www.getsync.com/">BitTorrent Sync</a></li>
<li><a href="http://syncthing.net/">Syncthing</a></li>
</ul>
<p>Both of these programs are very similar in that all they do is attempt to keep two folder in sync.</p>
<ul>
<li>Both use a cryptographic key to identify peers</li>
<li>Both are a pure sync and do not have the ability to share a file publicly</li>
<li>Both can add a device to an android phone using a QR code</li>
<li>Both have upload and download limits</li>
</ul>
<h4 id="bittorrentsync">BitTorrent Sync</h4>
<p>Pros:</p>
<ul>
<li>Windows, Linux and Android Clients</li>
<li>Can place placeholder files in a directory, showing that they exist, but not downloaded</li>
<li>Can work through NAT firewalls as it uses a public tracker</li>
</ul>
<p>Cons:</p>
<ul>
<li>Not open source</li>
<li>No versioning</li>
<li>When trying it out I somehow managed to create two identities and didn&apos;t know how to delete one on my android device.
<ul>
<li>I think identities see everything shared from every computer, but you can share between identies.</li>
</ul>
</li>
<li>Shows up using CPU even though no files are changing. (1-5% on windows)</li>
</ul>
<h4 id="syncthing">Syncthing</h4>
<p>Pros:</p>
<ul>
<li>Open Source</li>
<li>Can control which shares are shared with what computers</li>
<li>Can set a folder as a &quot;Folder Master&quot; which means it&apos;s essentially read-only to other computers - changes on other computers are not synced to this computer</li>
<li>Supports two types of file versioning
<ul>
<li>Simple versions, with a max count</li>
<li>Staggered versions up to a set time. A version up to every 30 seconds the first hour, Every hour up to 30 days, and then a week after that - Similar to a <a href="http://en.wikipedia.org/wiki/Backup_rotation_scheme#Grandfather-father-son">Grandfather-father-son</a> type backup. Can keep versions forever</li>
</ul>
</li>
<li>Has ignore patters to ignore syncing of certain files/directories - e.g. Can ignore .git directories!</li>
<li>Maxes out my upload if I let it.</li>
</ul>
<p>Cons:</p>
<ul>
<li>Requires opening firewall (UPnP or by hand) for communication - not an issue as I have a VPN configured between the backup systems</li>
<li>Windows automatic startup requires a separate program</li>
<li>Any configuration change requires a restart of the services, which breaks all connections</li>
<li>Android app is VERY alpha.. (not even beta)</li>
<li>Folders are identified by name only. So if computer one shares a folder named &quot;Photos&quot; and shared with Computer 2, it will be treated the same as a folder named &quot;Photos&quot; shared by Computer 3</li>
</ul>
<p>Meh&apos;s (for me.. might be Cons for a lot of people):</p>
<ul>
<li>No concept of users - every computer/installation is unique.</li>
<li>If a folder is shared with one computer, that computer can share it with others.</li>
</ul>
<h2 id="decision">Decision</h2>
<p>I think I&apos;m going to try Syncthing for starters. I will probably continue to use rsync for my Pictures backup (and probably most of the the things from my laptop). Unrelated, I plan on using <a href="http://gitolite.com/gitolite/index.html">Gitolite</a> for keeping a copy of my code and using it&apos;s mirror feature to back up my repositories.</p>
<p>If I find I absolutely need file sharing, I&apos;ve played around with Pydio a little bit and it looks like you can have a standard filesystem be the backing (with a normal tree layout) and configure it to just do sharing. Though that seems like overkill for something so simple that I want to do.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[BkPctf - Alewife]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The name of the file should have given us a hint as to the nature of the problem.. but it took me a while as I just started working on it and didn&apos;t pay attention to the name (nor see the problem description text).. and of course my</p>]]></description><link>https://www.r3dey3.com/2015-03-bkpctf-alewife/</link><guid isPermaLink="false">5ad628e9851f9800016ae783</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Mon, 02 Mar 2015 17:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>The name of the file should have given us a hint as to the nature of the problem.. but it took me a while as I just started working on it and didn&apos;t pay attention to the name (nor see the problem description text).. and of course my modus operandi is to reverse engineer things to find a vulnerablity, so I didn&apos;t connect but just dove into the reversed binary so I didn&apos;t pay attention to the ArrayOps string.</p>
<p>The problem was a pwnable, which meant that there was a vulnerability somewhere. My job was to find it. But first I had to understand what the program was doing as the only output strings were:</p>
<ul>
<li>&quot;**:&quot;</li>
<li>&quot;***:&quot;</li>
<li>&quot;ii:&quot;</li>
<li>&quot;iii:&quot;</li>
<li>&quot;ss:&quot;</li>
<li>&quot;sss:&quot;</li>
<li>&quot;ArrayOps\n&quot;</li>
<li>&quot;--:&quot;</li>
</ul>
<p>The input to the program is through three functions (as I named them), after printing a prompt they do their respective action.</p>
<ul>
<li>GetUint (0x400960) - gets up to 0x3f bytes into 0x40 sixed cleared stack buffer, then calls strtoul</li>
<li>GetInt (0x40097f) - gets up to 0x3f bytes into 0x40 sized cleared stack buffer, then calls atoi, returns value</li>
<li>Get_0x3f (0x400a04) - gets up to 0x3f bytes with a single read into a malloc&apos;d buffer</li>
</ul>
<p>Sadly, none of these were vulnerable to any overflow, so the bug had to be somewhere else.</p>
<!-- more -->
<p>After a while reversing we determined that the code allowed you to manage three types of arrays:</p>
<ol>
<li>Mixed String/Integer arrays.</li>
<li>Integer arrays</li>
<li>String arrays</li>
</ol>
<p>Each array was a fixed size of up to 256 elements, and you were limited to 32 of each type. The main function was a loop that allowed you to select the type of array, and then perform an action. After reversing we discovered the menu tree:</p>
<ul>
<li>1 - Mixed Arrays
<ul>
<li>1 - Allocate a new array</li>
<li>2 - More operations
<ul>
<li>1 - Add integer(s) to array</li>
<li>2 - Add string(s) to array</li>
<li>3 - Remove last element from array (decrement count)</li>
<li>7 - Subtract two integer values</li>
<li>8 - Add two interger values</li>
<li>9 - Concatenate two string values</li>
</ul>
</li>
<li>3 - Clear an array</li>
<li>4 - Print the array</li>
<li>5 - Copy the array to a non-mixed type</li>
</ul>
</li>
<li>2 - Integer Arrays
<ul>
<li>2 - More Operations
<ul>
<li>1 -  Replace array elements</li>
<li>3 - Sort array</li>
<li>4 - Remove the last element (decrement count)</li>
</ul>
</li>
<li>3 - Clear Array</li>
<li>4 - Print Array</li>
</ul>
</li>
<li>3 - String Arrays
<ul>
<li>2 - More Operations
<ul>
<li>2 - Replace array elements</li>
<li>3 - Sort arry</li>
<li>4 - Remove last element</li>
</ul>
</li>
<li>3 - Clear Array</li>
<li>4 - Print Array</li>
</ul>
</li>
</ul>
<p>All of the functions that would take an index verified the index was &gt;= 0 and &lt; 32. As you may have noticed, there is not a way to directly allocate a single-type array, you have to use the copy function, which requires all elements to be of the same type.</p>
<p>Each of the arrays used a structure:</p>
<pre><code class="language-language-c">//Structure for mixed array
//int is an 8 byte type
struct mixed_element {
	char type; // 2 = number, 3 = string
	char pad[7];
	struct {
		int value;
		FUNC_PTR to_str;
		FUNC_PTR add;
		FUNC_PTR subtract;
	} number;
	struct {
		char *ptr; //Pointer of the string from the user, allocated in heap as read by Get_0x1f
		FUNCPTR to_str;
		FUNCPTR strcat
	} str;
}

struct MixedArray {
	char allocated;
	char pad[7];
	mixed_element data[256];
	int numElements;
	FUNCPTR printFunction;
}
</code></pre>
<pre><code class="language-language-c">//Structure for Integer and String Arrays
struct array {
	char initialized;
	char pad[7];
	DATA_TYPE data[256]; //DATA_TYPE is int for integer arrary, char* for string arrays
	DATA_TYPE *pData; //Pointer to the start of data.
	int numElements;
	FUNCPTR printArray;
	FUNCPTR sort;
}
</code></pre>
<pre><code class="language-language-c">// Layout of BSS
MixedArray mixed_arrays[0x20]; // 0x602ec0
array int_arrays[0x20]; // 0x6831c0
array str_arrays[0x20]; // 0x6936c0
</code></pre>
<p>There&apos;s nothing there for type confusion as the values in the mixed array do not overlap, and the integer and string arrays are separate. But what does stand out is the pData member of the integer and string arrays, why is it needed if the array contents are statically allocated, if we could somehow get something into this pointer we could have a potential arbitrary write.</p>
<p>The print, to_str, sort, add, and subtract functions all looked ok. The strcat had a bug with it&apos;s use of realloc - if you passed in the same index to copy, it would free the data pointer (with realoc), but sadly, there wasn&apos;t a way to re-use the pointer as every read malloc&apos;d a new buffer.</p>
<p>So I then started looking at other functions. When I found get_int_array</p>
<pre><code class="language-language-c">int get_int_array() {  //0x400cd3
	int result;
	array *c;
	int idx;
	
	for (idx = 0; idx &lt; 0x20; idx++) {
		c = &amp;int_arrays[idx];
		result = is_initialized(c);
		if (!result) {
			int_array_ctor(c);
			return idx;
		}
	}
	return result;
}

//for completeness
int is_initialized(array *a)  { //0x400c5a
	return a-&gt;initialized;
}

void int_array_ctor(array *a) { //0x4021db
	a-&gt;pData = &amp;a-&gt;data;
	a-&gt;numElements = 0;
	a-&gt;initialized = 1;
	a-&gt;sort = SortIntArray;
	a-&gt;print = PrintIntArray;
	memset(a-&gt;pdata, 0, 0x256 * 8);
}
</code></pre>
<p>So it looks like that function always will return an empty freshly initialized array... but what happens if all the arrays are in use?<br>
It returns the value of the last is_initialized() call, which happens to be 1. Which means that whatever function was calling this that thought it was getting an empty array isn&apos;t. I had found the bug. But now how to use it as all the read functions from the user verify that we&apos;re not sending more than 256 values.</p>
<p>It turns out this function was only called in the copy_to function.<br>
The basic layout of the copy to function was:</p>
<pre><code class="language-language-c">int copy_to(mixed_idx, type) { //0x4016e2
	if 8mixed_idx &gt; 0x1f) 
		return -1;
	if (type == 2) {
		to_idx = get_int_array();
		if (copy_to_int(&amp;mixed_arrays[mixed_idx], &amp;int_arrays[to_idx]) != 0) {
			memset(&amp;int_arrays[to_idx], 0, sizeof(array));
			return -1;
		}
	}
	else if (type == 3) {
		to_idx = get_str_array();
		if (copy_to_str(&amp;mixed_arrays[mixed_idx], &amp;str_arrays[to_idx]) != 0) {
			memset(&amp;str_arrays[to_idx], 0, sizeof(array));
			return -1;
		}
	}
	return to_idx;
}
</code></pre>
<p>Not much there.. but if we looked at the individual copy to function:</p>
<pre><code class="language-language-c">int copy_to_type(MixedArray *mixed, array *ar) { //copy_to_int @ 0x400b69
	i = 0;
	if (mixed &amp;&amp; mixed-&gt;numElements &lt;= 0x100) {
		type *pData = ar-&gt;pData;
		while (i &lt; mixed-&gt;numElements) {
			mixed_element *c = &amp;mixed-&gt;data[i];
			if (c-&gt;flag != TYPE) { //TYPE == 2 for int, 3 for string
				return -1;
			}
			pData[i] = mixed_element-&gt;type.value;
			ar-&gt;numElements++;
			++v5;
		}
	}
</code></pre>
<p>Did you notice something above in copy_to_type? Even though the copy starts at element 0, the number of elements is never reset.</p>
<p>So it looks like we could make numElements greater than 256, however we can&apos;t just write arbitrary values.. as copy_to is always starting at index 0, and the replace array functions validate that we aren&apos;t sending more than 256 elements. But it turns out we have a very useful function, sort! All we need to do is inrease numElements and then sort the value we want into pdata.</p>
<p>One issue is that in order to use sort, I either need to have my desired pData be greater than the current value (meaning it&apos;s just pointing at other data or heap), or the function pointers get sorted to a bad value as they are less than the original pData. If all I needed was an arbitrary write that would be ok, but I need an info leak in order to make the exploit easier. I chose to two a two stage approach by first setting pData to iself, then changing it to my final desired value and restoring the function pointers in the first arbitrary write. Then leaking my information and finally getting execution control.</p>
<p>So now for the exploit (high level, as the implementation is left as an exercise for the reader)</p>
<ol>
<li>Create a new mixed array #0</li>
<li>Fill it with [0]*254 + [0xfffffff]*2</li>
<li>Copy the array 20 times to fill up all integer arrays</li>
<li>Create a new mixed array #1</li>
<li>Add some integers to the new mixed array. These values will be what we sort into pData
<ul>
<li>I added 4 copies of &amp;int_arrays[1].pData</li>
</ul>
</li>
<li>Copy mixed array #1 (it will go into int_array[1], and increase num_elements to 260)</li>
<li>Then sort the 2nd integer array (idx 1)
<ul>
<li>it&apos;s pData member now points to itself!</li>
</ul>
</li>
<li>Create a new mixed array #2</li>
<li>Add the values [ &amp;GOT, 0x40, &amp;PrintIntArray, &amp;SortIntArray ]</li>
<li>Copy the values from mixed #2; this will copy them to array idx 1 again, changing pData to point to the GOT, and restoring the function pointers (and making the size sane)</li>
<li>Call print int array with idx 1 to leak information about libc</li>
<li>Change the atoi entry in the GOT addresses we received to the address of system() based on the information we just leaked</li>
<li>Create a new mixed array #3</li>
<li>Put the updated GOT values into mixed #3</li>
<li>Copy mixed #3; which will overwrite the GOT</li>
<li>Now any value we send for a command is executed via system()</li>
<li>Run a shell!</li>
</ol>
<p>The final flag was: <strong>Because_C++_is_t00_hard!!!</strong></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[BkPctf - Kendall]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I was going to write how to solve Kendall, a &quot;pwn&quot; challenge, but the <a href="http://mweissbacher.com/">author</a> posted a nice <a href="http://mweissbacher.com/blog/2015/03/01/boston-key-party-2015-kendall-challenge-superfish/">write up</a></p>
<p>I probably spent a good hour and a half looking at the binary trying to see if something is exploitable (good job!) before I managed to figure out</p>]]></description><link>https://www.r3dey3.com/2015-03-bkpctf-kendall/</link><guid isPermaLink="false">5ad628e9851f9800016ae781</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Mon, 02 Mar 2015 03:01:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I was going to write how to solve Kendall, a &quot;pwn&quot; challenge, but the <a href="http://mweissbacher.com/">author</a> posted a nice <a href="http://mweissbacher.com/blog/2015/03/01/boston-key-party-2015-kendall-challenge-superfish/">write up</a></p>
<p>I probably spent a good hour and a half looking at the binary trying to see if something is exploitable (good job!) before I managed to figure out the DNS request part. I only managed to find two bugs:</p>
<ul>
<li>You could remove the null terminator on the IP address by writing an address of exactly 16 bytes (eg &quot;1111111111111111&quot;)</li>
<li>If you made the Source, Dest, and netmask all 16 bytes, and the Nameserver 3, the renew_client would print an error. This was due to the snprintf before the system being truncated.</li>
</ul>
<p>I did learn an important lesson. If there&apos;s an opportunity to put a hostname or ip somewhere <strong>PUT IN AN IP YOU CONTROL</strong></p>
<p>I ended up using dnsmasq for dns as I had a server that wasn&apos;t running dns. I&apos;ll have to take a look at <a href="https://code.google.com/p/minidns/">minidns</a> for next time. I ended up using python&apos;s SimpleHTTPServer:</p>
<pre><code class="language-language-bash">python -m SimpleHTTPServer 80
</code></pre>
<p>And a real simple HTTPs server I <a href="http://www.piware.de/2011/01/creating-an-https-server-in-python/">found</a> on the web</p>
<pre><code class="language-language-python">import BaseHTTPServer, SimpleHTTPServer
import ssl
 
httpd = BaseHTTPServer.HTTPServer((&apos;0.0.0.0&apos;, 443), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile=&apos;./server.pem&apos;, server_side=True)
httpd.serve_forever()
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[BkPctf - Wood Island and Orient Heights]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>This weekend was the <a href="http://bostonkey.party">Boston Key Party Ctf</a>. There were a bunch of challenge, and my team did pretty well (top 10) even though we didn&apos;t have a lot of our regulars. Two of the problems involved signing a string &quot;There is no need to be upset&</p>]]></description><link>https://www.r3dey3.com/2015-03-bkpctf-wood-island-and-orient-heights/</link><guid isPermaLink="false">5ad628e9851f9800016ae782</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Mon, 02 Mar 2015 02:18:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>This weekend was the <a href="http://bostonkey.party">Boston Key Party Ctf</a>. There were a bunch of challenge, and my team did pretty well (top 10) even though we didn&apos;t have a lot of our regulars. Two of the problems involved signing a string &quot;There is no need to be upset&quot; using <a href="http://en.wikipedia.org/wiki/ElGamal_signature_scheme">Elgamal signing</a>.</p>
<p><strong>The TLDR version is both failed in the duplicate checks.</strong></p>
<p>Both problems required &quot;proof of work&quot; prior to the signing test:</p>
<ol>
<li>Server reads 9 bytes of random data and generates a base64 encoded version</li>
<li>Sever sends the base64 to client (12 bytes)</li>
<li>Client adds up to 8 bytes</li>
<li>Server then verifies first 12 are the ones it sent</li>
<li>Server computes SHA1 hash of all 20 bytes</li>
<li>Hash must end with 24 bits of 0 to pass</li>
</ol>
<p>Once you passed the proof of work you had to send the message (&quot;There is no need to be upset&quot;) and signature (r and s). The format of the message and signature was json with Wood Island, and asn1 with Orient Heights. If the signature passed you were rewarded with the key.</p>
<p>Along with the server script and the key information, we were given a collection of valid signatures, lest we had to brute force up to a 1024 bit private key. However, even though the message that the server wanted was in the example signatures, the server checked that we weren&apos;t sending a duplicate signature.</p>
<p>Here in lies the flaw we used. Wood Island used the python json library to decode the string into a dict and the duplicate check was a simple &quot;user_dict in list&quot; check. Adding a field to the json was enough to pass the check.  Orient Heights just compared the binary ASN1 encoding; once again adding a field caused it to fail.</p>
<!-- more -->
<p>Now for how you are supposed to solve them... Looking at the list of signatures, we noticed that there was a few that used the same value for r. Elgamal signing has a known issue that if you use the same value for r (really the random k), then you can compute the private key using Linear Congruence. There&apos;s a nice <a href="http://crypto.stackexchange.com/questions/1479/elgamal-signature-scheme-recovering-the-key-when-reusing-randomness">question and answer on cryto.stackexchange</a> on how to do it. Of course I wasn&apos;t quite up to speed on my Linear Congruence, so I found a <a href="http://www.johndcook.com/blog/2008/12/10/solving-linear-congruences/">helpful page</a> on how to solve them.</p>
<pre><code class="language-language-python">#!/usr/bin/python

from dsa_key import *
import dsa
import hashlib
from dsa_prime import *
from dsa import elgamal_verify as verify
import code
import json
DUPLICATES = open(&apos;sigs.txt&apos;, &apos;r&apos;).read().split(&apos;\n&apos;)[:-1]
DUPLICATES = map(json.loads, DUPLICATES)

#Read the signatures
with open(&quot;sigs.txt&quot;, &quot;rb&quot;) as f:
	lines = f.read().split(&apos;\n&apos;)[:-1]

d = map(lambda v: json.loads(v, encoding=&quot;utf8&quot;), lines)
# Find only have valid
#working = [i for i in d if verify(**i)]

# I saved them off in a single json file to make things faster
working = json.load(open(&quot;working&quot;))
d = working

# expected value
expected = &quot;There is no need to be upset&quot;
# The function to convert a string message into the hash for signing
hash_val = lambda m: int(hashlib.sha384(m.encode(&quot;utf8&quot;)).hexdigest(), 16)
e_hash = hash_val(expected)


r_list = [ i[&quot;r&quot;] for i in working ]
dup_r = [ i for i in r_list if r_list.count(i)&gt;1][0]
 
dups = [ i for i in working if i[&quot;r&quot;]==dup_r]
import gmpy
from gmpy import mpz
from gmpy import gcd

g = mpz(GENERATOR)
p = mpz(SAFEPRIME)

s = [ mpz(i[&quot;s&quot;]) for i in dups ]
r = [ mpz(i[&quot;r&quot;]) for i in dups ]
m = [ mpz(hash_val(i[&quot;m&quot;])) for i in dups ]


# SOLVING k(s[0] - s[1]) = (m[0] - m[1]) mod p-1
# ka = side2 mod p-1
a = s[0] - s[1]
side2 = m[0] - m[1]

num = gcd(a, p-1)
num = int(num)
print num

k_ = gmpy.divm(side2/num, a/num, (p-1)/num)
for i in range(0,num):
	k = k_ + (i*(p-1)/num)
	r_ = pow(g, k, p)
	if r_ == r[0]:
		print &quot;FOUND K&quot;
		break

# solve xr  = (m0 - ks0) mod p -1
side2 = m[0] - k * s[0]
num = int(gcd(r[0], p-1))

x_ = gmpy.divm(side2/num, r[0]/num, (p-1)/num)
for i in range(0, num):
	x = x_ + (i*(p-1)/num)
	y = pow(g, x, p)
	if y == PUBKEY:
		print &quot;FOUND x&quot;
		break

def sign(m_str):
	if type(m_str) in [str, unicode]:
		m = hash_val(m_str)
	else:
		m = m_str
	
	k = 55
	r = pow(g, k, p)
	s = gmpy.divm(m - x*r, k, p-1)
	return {&quot;s&quot;: s, &quot;r&quot;:r, &quot;m&quot;:m_str}

</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[LED Tie Bar - Software]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://www.r3dey3.com/content/images/2016/09/tie-bar-on-box.jpg" alt loading="lazy"><br>
The software isn&apos;t my best work. I did try to make the effects and color generation abstract, which is why I ended up using a Teensy vs an Trinket Pro or similar. I just needed more processing power.</p>
<p>The software that was loaded when I gave them out</p>]]></description><link>https://www.r3dey3.com/2014-12-led-tie-bar-software/</link><guid isPermaLink="false">5ad628e9851f9800016ae77f</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Wed, 31 Dec 2014 00:45:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://www.r3dey3.com/content/images/2016/09/tie-bar-on-box.jpg" alt loading="lazy"><br>
The software isn&apos;t my best work. I did try to make the effects and color generation abstract, which is why I ended up using a Teensy vs an Trinket Pro or similar. I just needed more processing power.</p>
<p>The software that was loaded when I gave them out as gifts is available at <a href="https://github.com/r3dey3/led/tree/tie_bar_v1">https://github.com/r3dey3/led/tree/tie_bar_v1</a></p>
<!-- more -->
<p>One of the neat things I did, was instead of using a ground pin for the inputs (button, and jumper) I simply set on of the pins as an INPUT_PULLUP and the other as an output set to LOW. This isn&apos;t an issue for the button, as it&apos;s only momentarily pressed, but in order to not waste power through the pullup to ground (I know, it wouldn&apos;t be <em>that</em> much) I just check the status of the jumper at startup after setting the state of both pins, waiting, then set both pins to tri-state by setting them to INPUT)</p>
<pre><code class="language-c">bool ColorsEnabled() {
	//Check if jumper is in place
	
	pinMode(17, OUTPUT);
	digitalWrite(17, LOW);
	pinMode(19, INPUT_PULLUP);
	delay(5); //give things a slight chance to stabilize 
	bool enableColors = digitalRead(19);
	pinMode(17, INPUT);
	pinMode(19, INPUT);
	return enableColors;
}
</code></pre>
<p>There will be more written here hopefully after the honeymoon. Just ran out of time write stuff.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[LED Tie Bar - Hardware]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://www.r3dey3.com/content/images/2016/09/tie-bar-assembled.jpg" alt loading="lazy"></p>
<h2 id="partslist">Parts list</h2>
<p>For each:</p>
<ul>
<li>Generic Metal Tie Bar - <a href="http://amzn.com/B00E5YW8L6">http://amzn.com/B00E5YW8L6</a></li>
<li>Teensy 3.1 - <a href="https://www.adafruit.com/products/1625">https://www.adafruit.com/products/1625</a></li>
<li>NeoPixel Stick w/8 Pixels - <a href="https://www.adafruit.com/products/1426">https://www.adafruit.com/products/1426</a></li>
<li>Micro Lipo Charger - <a href="https://www.adafruit.com/products/1304">https://www.adafruit.com/products/1304</a></li>
<li>500mAh LiPo Battery - <a href="https://www.adafruit.com/products/1578">https:</a></li></ul>]]></description><link>https://www.r3dey3.com/2014-12-led-tie-bar-hardware/</link><guid isPermaLink="false">5ad628e9851f9800016ae77d</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Wed, 31 Dec 2014 00:44:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://www.r3dey3.com/content/images/2016/09/tie-bar-assembled.jpg" alt loading="lazy"></p>
<h2 id="partslist">Parts list</h2>
<p>For each:</p>
<ul>
<li>Generic Metal Tie Bar - <a href="http://amzn.com/B00E5YW8L6">http://amzn.com/B00E5YW8L6</a></li>
<li>Teensy 3.1 - <a href="https://www.adafruit.com/products/1625">https://www.adafruit.com/products/1625</a></li>
<li>NeoPixel Stick w/8 Pixels - <a href="https://www.adafruit.com/products/1426">https://www.adafruit.com/products/1426</a></li>
<li>Micro Lipo Charger - <a href="https://www.adafruit.com/products/1304">https://www.adafruit.com/products/1304</a></li>
<li>500mAh LiPo Battery - <a href="https://www.adafruit.com/products/1578">https://www.adafruit.com/products/1578</a></li>
<li>JST-PH 2-Pin Breakout Board - <a href="https://www.adafruit.com/products/1862">https://www.adafruit.com/products/1862</a></li>
</ul>
<p>Other parts used:</p>
<ul>
<li>Tactile Switch (6mm slim) - <a href="https://www.adafruit.com/products/1489">https://www.adafruit.com/products/1489</a></li>
<li>Extra long break away male header - <a href="https://www.adafruit.com/products/400">https://www.adafruit.com/products/400</a></li>
<li>Silicone Cicoil wire - 4 pin, 24 AWG - <a href="https://www.adafruit.com/products/1437">https://www.adafruit.com/products/1437</a></li>
</ul>
<!-- more -->
<h2 id="shematic">Shematic</h2>
<p>This is going to be described as I don&apos;t have a picture and it&apos;s pretty simple. The picture shows almost all the connections. What you don&apos;t see are the power and ground coming from the breakout to the silicone cable.<br>
<img src="https://www.r3dey3.com/content/images/2016/09/tie-bar-top-view.jpg" alt loading="lazy"></p>
<ul>
<li>Power and ground from the JST Breakout goes to both the Teensy and the NeoPixels</li>
<li>The button is soldered onto the Teensy between pins 20 and 23</li>
<li>The jumper is soldered onto the Teensy between pins 17 and 19</li>
<li>The Input of the NeoPixels is soldered to pin 7 of the Teensy</li>
</ul>
<h2 id="electronicsassembly">Electronics Assembly</h2>
<p><img src="https://www.r3dey3.com/content/images/2016/09/tie-bar-side-view.jpg" alt loading="lazy"><br>
Sadly I don&apos;t have any pictures during assembly. I ended up doing things in assembly line fassion as I was making 10 of them. It really helped me hone my process.<br>
The image to the right shows how the silicone cable is soldered to the underside of the JST breakout, which after trial and error seemed to be the best way to connect the power and cables to keep everything as compact as possible.<br>
The steps that I ended up taking were:</p>
<ol>
<li>Solder the button to the Teensy</li>
<li>Solder the jumper to the Teensy, on the ones for gifts I used an extra long header that I bent into a U shape to go between the pins</li>
<li>Solder a standard size male header pin to the outside ground pin on the JST breakout, long side sticking out the bottom</li>
<li>Solder a extra long male header pin to the outside positive pin on the JST breakout, on the TOP</li>
<li>Trim the silicone wire so that two wires are shorter, and the other two have enough to reach to pin 7</li>
<li>Strip the short wires</li>
<li>Solder the short wires to the bottom of the JST breakout (both + and -), so that the extra wires are on the + side</li>
<li>Cut back the 4th wire from the silicon (if what was soldered to the minus side of the JST breakout is now the 1st)</li>
<li>Strip the 3rd wire and solder it to Teensy Pin 7</li>
<li>Add an extra black spacer to the long header breakout that is in the + side of the JST heder</li>
<li>Bend said header over so it will reach the + pin of the Teensy</li>
<li>Solder both the - and + on the Teensy</li>
<li>Strip all 4 wires of the other end of the silicone cable. What I found works best is just taking an x-acto knife and pressing it to each flat side of the cable and pulling the piece off, stripping all 4 at once</li>
<li>Tin all 4 wires</li>
<li>Solder the 4 wires to the back of the NeoPixels</li>
<li>Sand the surface of the tie bar to expose raw metal</li>
<li>Tin the surface of the tie clip</li>
<li>Solder the Neopixels through the mounting screw holes to the tie clip. I made a little jig to hold the tie clip (because it got HOT) and the Neopixels in place so every one was very close to the same position. This required a lot of solder to bridge the gap</li>
</ol>
<p><img src="https://www.r3dey3.com/content/images/2016/09/tie-bar-bar-led-solder.jpg" alt loading="lazy"></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[LED Tie Bar - Overview]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://www.r3dey3.com/content/images/2016/09/tie-bar-hanging.jpg" alt loading="lazy"><br>
For my groomsmen gift for my wedding, I decided to do an LED tie bar. I think it turned out pretty well. Hopefully they will all like them (and they don&apos;t see this before they get them!)</p>
<p>The bar is a metal tie bar with a 8 NeoPixel</p>]]></description><link>https://www.r3dey3.com/2014-12-led-tie-bar-overview/</link><guid isPermaLink="false">5ad628e9851f9800016ae77e</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Wed, 31 Dec 2014 00:43:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://www.r3dey3.com/content/images/2016/09/tie-bar-hanging.jpg" alt loading="lazy"><br>
For my groomsmen gift for my wedding, I decided to do an LED tie bar. I think it turned out pretty well. Hopefully they will all like them (and they don&apos;t see this before they get them!)</p>
<p>The bar is a metal tie bar with a 8 NeoPixel (WS2812B) LEDs on it. There is a microcontroller with a push button switch on back for changing the effects and colors. However, as the wedding colors are blue and silver, there is a jumper in place that limits the colors to blue. Cutting this jumper will enable the full range of colors.</p>
<p>The effects are:</p>
<ul>
<li>Fickering</li>
<li>Cylon</li>
<li>Theater chase in one direction</li>
<li>Theater chase in the other direction</li>
<li>Fade between dim and bright and back</li>
<li>Fade between on and off</li>
<li>Fade between on and white</li>
<li>Sin mix between color and black (like Cylon, but only one direction)</li>
<li>Sin mix (black) in other direction</li>
<li>Sin mix between dim and bright in either direction</li>
<li>Sin mix between on and white in either direction</li>
<li>Blinking</li>
<li>On Dim</li>
<li>On Medium</li>
<li>On Bright (very very bright)</li>
</ul>
<!-- more -->
<p>Once the jumper on the back is cut, the full list of colors is:</p>
<ul>
<li>Blue</li>
<li>Purple</li>
<li>Red</li>
<li>Yellow</li>
<li>Green</li>
<li>Cyan</li>
<li>Rainbow (each led a different color)</li>
<li>Rainbow cycle slow (bar is a solid color, but it cycles through the HSV spectrum by hue)</li>
<li>White</li>
<li>Rainbow cycle fast</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[DEF CON 2014 Finals – wdub v2]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Once again I&#x2019;m gonna talk about the 2nd version of a service from DEF CON 22&#x2019;s CTF finals. This time it&#x2019;s wdub; a simple HTTP server.<br>
Version 1 had an integer overflow which lead to a stack overflow.<br>
(edit: DEF CON CTF Challenges available</p>]]></description><link>https://www.r3dey3.com/2014-08-def-con-2014-finals-wdub-v2/</link><guid isPermaLink="false">5ad628e9851f9800016ae77c</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Wed, 13 Aug 2014 16:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Once again I&#x2019;m gonna talk about the 2nd version of a service from DEF CON 22&#x2019;s CTF finals. This time it&#x2019;s wdub; a simple HTTP server.<br>
Version 1 had an integer overflow which lead to a stack overflow.<br>
(edit: DEF CON CTF Challenges available @ <a href="http://shell-storm.org/repo/CTF/Defcon-22-finals/" target="_blank">http://shell-storm.org/repo/CTF/Defcon-22-finals/</a>)</p>
<p>It turned out version 2 had two bugs. A use after free, and an integer overflow buf. To start with version 2 added a new http method &#x2013; EVAL, where it ran something over the POST contents (with optional decompression), it also made POST requests to a file ending in ydg a script type page with &lt;?ydg tags&#x2026; that causes the same evaluating to happen.</p>
<!-- more -->
<p>I spent the first bit of time reversing the new command to figure out what it was doing as I didn&#x2019;t have an SLA check network traffic yet. The first part was figuring out the language. It turned out to be a simple</p>
<pre><code class="language-language-c">var = command arg1 arg2 ...  
OR 
command arg1 arg2 ...
</code></pre>
<p>Depending on if the command allocated a new variable.</p>
<p>The commands:</p>
<pre>[name]=gimme [size] - allocate item
  - first 4 bytes of data is size... 
Yo [name] - lookup item:
  switch field8
    if 1,2,3 copy 0,1,3 btytes of databuf to output
    else copy *databuf (int) bytes to output
putitin [item1] [item2]  [item3 or num] - FIXED SIZE ONLY
	offset = item3.data or num
	memcpy(item1 + offset, item2, item2.size)
pullitout [item1] [item2] [item3 or num] - FIXDED SIZE ONLY
	offset = item3.data or num
          memcpy(item1, item2+offset, item1.size)

nomo [item] - free item
[name]=dupme [old_name] - duplicate item
[name]=shebewalkinfunny [number] - new 4 byte number
[name]=datbetta [number] - new 2 byte number
[name]=pobastard [num] - new 1 byte number
[name]=makeit [num] - expand buffer

bonut [name] [offset] - bit invert
  if not 1,2,4 byte value: bit flip byte at offset (+4)
oudahere [name] [num1] [num2] - delete num2 bytes at num1 from name; no check on type of item (arb length or fixed length)**

putdatader [name1] [name2]  - append item2 to item1 (arb data only)
slipitin [item1] [item2] [offset] - insert item2 into item 1 at offset (arb data only)
slapitup [item1] [item2] [item3_or_offset] - copy item2 into item1 at offset (overwrite) (arb data only)

[name]=moagin, eatdata, splitdat, screwdat [item2_or_num] [item3_or_num];
  +, -, *, / 
  name = num1 OP num2
  if item1 doesn&apos;t exist, creates 4 byte item

exite, bandit, borit [item1] [num] - for fixed size items
  xor, and, or
  item = item1 OP num
exite, bandit, borit [item1] [offset] [num] - for var size items
  xor, and, or
  item[offset] OP= num (byte)

deyseme ... bit shifts
 &gt;&gt;, &lt;&lt;, ror, rol
</pre>
<p>The use after free bug is due to the dupme command not doing a deep duplication. It only duplicates the data storage structure of:</p>
<pre><code class="language-language-c">char* name
char* data; //if a buffer it&apos;s a pascal style string buffer with the length being the first 4 bytes, otherwise it&apos;s a pointer to a 1, 2, or 4 byte buffer
int type; //0 - buffer, 1- char, 2 - short, 3 - dword
</code></pre>
<p>However the bug I went after was in the putitin command &#x2013; something that would copy a 1,2,4 byte value into an offset location in a buffer. It turns out the check for if this size of the buffer is large enough was written like:</p>
<pre><code class="language-language-c">if (offset + 4 &lt;= *(uint32_t*)(dest-&gt;data)) ...
</code></pre>
<p>Now if you can notice here.. if offset == -4, then offset+4 will be 0.. and 0 is &lt; = any unsigned value. So good.. we can overflow the offset.. well what happens with that.. it turns out the copy to copy the data is:</p>
<pre><code class="language-language-c">memcpy((dest-&gt;data)+4+offset, src, 4)
</code></pre>
<p>And from the fact that the &#x201C;size of buffer&#x201D; is stored at the first 4 bytes of the data pointer (eg pascal strings) we can set the size to whatever we want.. which means if we set it to -1, we can then write ANYWHERE in memory.</p>
<p>Well that&#x2019;s great.. ASLR is enabled.. well .. looking at the structures used, it turns out that the eval structure, has an field for length written (using the Yo command to write).. well we can change that length as we know the relative offset of that field to our allocated data (deterministic heap ftw)</p>
<p>Structure used to store eval results:</p>
<pre><code class="language-language-c">struct eval_result
char *outBuf;
uint32_t bytesout;
...
</code></pre>
<p>The outBuf is set by the function calling into the eval, and is a stack variable. it then uses the bytesOut to send the data at that location to the client. Well now we can leak addresses&#x2026;</p>
<p>So we now know where the stack is. And since we can write anywhere, we can change the address of the data pointer in our buffer once we change the size&#x2026; then we can change the stack..</p>
<p>So the final sequence is:</p>
<pre><code class="language-language-python">&quot;b=gimme 4&quot;
&quot;c=shebewalkinfunny -1&quot;
&quot;putitin b c -4&quot; #enable write anwhwere
&quot;d=shebewalkinfunny 1024&quot; #how much we want to leak
&quot;putitin b d -424&quot; #offset of data point to bytesOut
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[DEF CON 2014 Finals - imap v2]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>This year, like last <a href="https://legitbs.net/">LegitBS</a> released updated services part way through the competition with the old vulnerabilities fixed and new ones. The first imap service (implements the IMAP protocol) had a bug in the SELECT command that would overflow the mailbox name, allowing one to change the username to &#x201C;</p>]]></description><link>https://www.r3dey3.com/2014-08-dc2014_finals-imap-v2/</link><guid isPermaLink="false">5ad628e9851f9800016ae77b</guid><dc:creator><![CDATA[Kenny K]]></dc:creator><pubDate>Mon, 11 Aug 2014 16:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>This year, like last <a href="https://legitbs.net/">LegitBS</a> released updated services part way through the competition with the old vulnerabilities fixed and new ones. The first imap service (implements the IMAP protocol) had a bug in the SELECT command that would overflow the mailbox name, allowing one to change the username to &#x201C;.&#x201D; which would then allow listing/reading all users mail (things were stored in a directory per user)</p>
<p>(edit: DEF CON CTF Challenges available @ <a href="http://shell-storm.org/repo/CTF/Defcon-22-finals/" target="_blank">http://shell-storm.org/repo/CTF/Defcon-22-finals/</a>)</p>
<p>But in v2, this bug was fixed&#x2026; instead it was MUCH more evil. instead of being stored in plain text, messages were base64 encoded. Not a huge deal, but what was weird was the message was base64 decoded in the STORE handler. This command only updates message flags, there&#x2019;s no need to decode the contents&#x2026; Encoded messages were limited to 1000 bytes, which means that a decoded message could be 750 bytes large&#x2026; turns out the buffer that the message was decoded in was only 740 bytes&#x2026; this allowed us to overflow whatever came after the buffer. It turns out this was a pointer to the flags, which were written right before the function returned. It&#x2019;s only a 1 byte write &#x2026; with only control over bits 1-6 (0-7 numbering). Bit 7 was always 1, and you could either leave bit 0 as is, or clear it. The basic pseudo code was:</p>
<!-- more -->
<pre><code class="language-language-c">    update_flags(aMode, aFlags) {
    int len;
    int new_flags;
    uint8_t flags;
    char decoded_buf[740];
    uint8_t *pFlags;
    char encoded_buf[1000];
    get_message(&amp;buf, &amp;flags, len);
    base64_decode(encoded_buf, len, decoded_buf);
    new_flags = parse_flags(aFlags); // bit or of result of parse with 0x80
    if (mode == SET_ALL) // command option is FLAGS
        *pFlags = new_flags;
    if (mode == SET) // command option is +FLAGS
        *pFlags |= new_flags;
    if (mode == CLEAR) //command option is -FLAGS
        *pFlags ^= new_flags; //xor
        *pFlags |= 0x80
    store_flags(...);
}
</code></pre>
<p>Now the question is what to write.. luckily there was also an info leak .. Messages were given a unique id that was randomly generated when the mailbox was created. It so happened that the random numbers were not actually the result of calling rand.. (intentional&#x2026;) one turned out to be the stack canary, the other was an address on the stack.. So now we know the address of the stack, and the stack canary for our fake stack frame&#x2026; now how do we get a stack frame where it&#x2019;ll be used. This was the hardest part.. now luckily the stack was executable.. but we couldn&#x2019;t just change a return address because we didn&#x2019;t know the value present and we couldn&#x2019;t write the low bit and stacks are all in high memory..</p>
<p>It turns out that main uses r7 as a frame pointer, and the update_flags function stores this variable on the stack for us. we could change main&#x2019;s frame pointer, and when it goes to return it may read from space we have control over.. well first I just tried moving r7 by a small amount, that way the previous command input would be used as the stack.. however this has a problem &#x2013; if we only change r7 by a small amount (512) we are still close to sp.. and when main would call bzero, the data buffer that was being cleared was part of the stack frame for bzero, which would mean r7 was cleared and main would then crash. Eventually I found the function that handles the FETCH command. it has a very large stack frame and the decoded message is read info a buffer.. I could move r7 to point to an address that when used by main to return would point to the message data.</p>
<p>So that was the &#x201C;easy&#x201D; part..the next part was dealing with ASLR.. not only was simple ASLR turned on where the page address changed, but the stack randomization was turned on as well. which meant that the stack was aligned at 256 byte boundaries (meaning 24 bits of random).. and I was trying to reduce the frame by an order of 3000 bytes.. I needed to calculate not only the necessary flags (stored as bitfield) to change r7, but also the new return address (luckily stack was rwx), offset of the stack canary and return address in my message that will be used as the stack frame</p>
<p>So final sequence was:</p>
<ol>
<li>Create mailbox</li>
<li>Leak stack canary and stack address with EXAMINE command</li>
<li>Calculate address of various things on stack</li>
<li>Determine a valid address i can set r7 to that will put the return address of main into my buffer, not the offset of the frame end</li>
<li>Create messages that will allow me to set low two bytes of r7</li>
<li>Create message &#x2013; main&#x2019;s new stack frame, using the offset calculated</li>
<li>Send STORE to update 2nd lowest byte of r7 (jump far away first, as main does bzero and we don&#x2019;t want to overwrite stored stack frames)</li>
<li>Send STORE to update low byte of r7</li>
<li>Send FETCH to retrieve stack frame</li>
<li>Return from main</li>
</ol>
<p>Actual implementation is left as an exercise to the reader. Sadly I wasn&#x2019;t quite able to get this done during the competition.. going on no sleep Saturday night was a little hard.. I was close, I just failed to use my calculated offset in the calculation of the return address.. everything else was in place.. of course then getting shellcode to find the key in the messages was the next step.. and that wasn&#x2019;t done.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>