Louis-Philippe Véronneau - sage50https://veronneau.org/2017-06-08T00:00:00-04:00Recover Lost Sage 50 (Simply Accounting) Password with Free Software2017-06-08T00:00:00-04:002017-06-08T00:00:00-04:00Louis-Philippe Véronneautag:veronneau.org,2017-06-08:/recover-lost-sage-50-simply-accounting-password-with-free-software.html<p>Today the person managing the finances where I work told me she needed to access
old simply accounting (now Sage 50) files on the legacy Windows computer we
keep for that kind of reason.</p>
<p>We switched to LibreOffice Calc for our accounting when I started working there,
but the company …</p><p>Today the person managing the finances where I work told me she needed to access
old simply accounting (now Sage 50) files on the legacy Windows computer we
keep for that kind of reason.</p>
<p>We switched to LibreOffice Calc for our accounting when I started working there,
but the company used to use Sage 50.</p>
<p>The plan seemed simple: open the files and export the data to CSV. Sadly the
file was password protected and no one could remember what damn password they
used.</p>
<p>If you are reading this, please take a moment to reflect on your password
policies. People like me have to deal with shit like this because people still
don't use password managers. It's simple: USE A PASSWORD MANAGER! NO MORE
FREAKING LOST PASSWORDS, YO!</p>
<p><img src="/media/blog/2017-06-08/roll-safe.jpg" title="Roll Safe meme: You can't forget your passwords if you never had any" alt="Roll Safe meme: You can't forget your passwords if you never had any" style="padding-left:15%"></p>
<p>I recommend using <a href="http://keepass.info/">KeePass</a> if you are using Windows and
<a href="https://keepassxc.org/">KeepassXC</a> under Linux.</p>
<p>Anyway, back to the main topic: how the hell can one open a Sage 50 database
when you lost the password?</p>
<p>There are some shady Windows executables you can buy online that claims they
will recover your lost Sage 50 passwords, but do you really trust all your
financial data to some random programmer on the web asking 60$? Best case
scenario you lost 60$ and you get your password back. Worst case, some Russian
hacker now has your employee's private informations.</p>
<p>So yeah, please don't download these things and read on.</p>
<h2>Prerequisites</h2>
<p>It turns out Sage 50 uses MySQL as a backend to save its data. To gain back
access to that file we'll thus extract the database used by your file and
replace the sysadmin password in it by a known one.</p>
<p>For that, you will need:</p>
<ul>
<li>A Windows computer running Sage 50</li>
<li>A Debian computer</li>
<li>Some patience and a little familiarity with the command line</li>
</ul>
<p>It is best if the computer running Debian Gnu/Linux is a "disposable" one, or at
least a computer that is not running MySQL for anything important. We'll be
playing with MySQL quite a little and my instructions will overwrite any
configurations or databases MySQL uses.</p>
<h2>Extracting the database</h2>
<p>The file you are trying to open is likely an automatic backup copy Sage 50 saved
somewhere. Those files are <a href="https://en.wikipedia.org/wiki/Cabinet_%28file_format%29">.CAB</a> files, a type of lossless compression
archive Windows uses.</p>
<p>Copy the <code>.CAB</code> file to your Debian computer. If the computer has a graphic
interface, the easiest way to extract the archive is to open it with
<code>file-roller</code>. If it is not installed by default, you can install it by running:</p>
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>apt<span class="w"> </span>install<span class="w"> </span>file-roller
</code></pre></div>
<p>On a headless computer, you will need to use <code>cabextract</code>.</p>
<p>Once you extracted the files, you should end up with something like this:</p>
<pre>
├── file_name.SAI
└── file_name.SAJ
├── errorlog.txt
├── ExceptionError.log
├── ibdata1
├── ib_logfile0
├── ib_logfile1
├── mysql
│ ├── columns_priv.frm
│ ├── columns_priv.MYD
│ ├── columns_priv.MYI
│ ├── db.frm
│ ├── db.MYD
│ ├── db.MYI
│ ├── func.frm
│ ├── func.MYD
│ ├── func.MYI
│ ├── help_category.frm
│ ├── help_category.MYD
│ ├── help_category.MYI
│ ├── help_keyword.frm
│ ├── help_keyword.MYD
│ ├── help_keyword.MYI
│ ├── help_relation.frm
│ ├── help_relation.MYD
│ ├── help_relation.MYI
│ ├── help_topic.frm
│ ├── help_topic.MYD
│ ├── help_topic.MYI
│ ├── host.frm
│ ├── host.MYD
│ ├── host.MYI
│ ├── proc.frm
│ ├── proc.MYD
│ ├── proc.MYI
│ ├── procs_priv.frm
│ ├── procs_priv.MYD
│ ├── procs_priv.MYI
│ ├── tables_priv.frm
│ ├── tables_priv.MYD
│ ├── tables_priv.MYI
│ ├── time_zone.frm
│ ├── time_zone_leap_second.frm
│ ├── time_zone_leap_second.MYD
│ ├── time_zone_leap_second.MYI
│ ├── time_zone.MYD
│ ├── time_zone.MYI
│ ├── time_zone_name.frm
│ ├── time_zone_name.MYD
│ ├── time_zone_name.MYI
│ ├── time_zone_transition.frm
│ ├── time_zone_transition.MYD
│ ├── time_zone_transition.MYI
│ ├── time_zone_transition_type.frm
│ ├── time_zone_transition_type.MYD
│ ├── time_zone_transition_type.MYI
│ ├── user.frm
│ ├── user_info.frm
│ ├── user_info.MYD
│ ├── user_info.MYI
│ ├── user.MYD
│ └── user.MYI
├── simply
│ ├── db.opt
│ ├── palrtres.frm
│ ├── pqueue.frm
│ ├── psptrdt.frm
│ ├── psptrdtp.frm
│ ├── psptrdtt.frm
│ ├── psptr.frm
│ ├── psptrtax.frm
│ ├── pstatus.frm
│ ├── pstrdtts.frm
│ ├── ptrans.frm
│ ├── ptrsnum.frm
│ ├── simplygroupmembership.frm
│ ├── simplygrouppriv.frm
│ ├── simplyusergroup.frm
│ ├── taccount.frm
│ ├── .
│ ├── .
│ ├── .
│ ├── tuser.frm
│ ├── tuserfrm.frm
│ ├── tuserinv.frm
│ ├── tuserlog.frm
│ ├── tuserprf.frm
│ ├── tuserwnd.frm
│ ├── tusrmsg.frm
│ ├── tusrpane.frm
│ ├── tusrpopt.frm
│ ├── tusrprf2.frm
│ ├── tusrrmsg.frm
│ ├── tusrrole.frm
│ ├── tusrrpt.frm
│ ├── tusrrrpt.frm
│ ├── tvendor.frm
│ ├── tvendp.frm
│ ├── tvendplg.frm
│ ├── tveninv.frm
│ ├── tvenitem.frm
│ ├── tvenmemo.frm
│ ├── tventrdt.frm
│ ├── tventr.frm
│ ├── tventxdt.frm
│ └── tvenudf.frm
└── SimplyError.log
</pre>
<p>So yeah, you end up with a very small file (the <code>.SAI</code> file) and one larger
directory (the <code>.SAJ</code> directory).</p>
<p>The <code>.SAI</code> is basically a unicode string describing the database to Sage 50.
That's the file you click on in Windows to access the database. Sage 50 will
read whatever <code>.SAJ</code> directory that has the same name the <code>.SAI</code> file has, so be
sure to keep the two named the same way.</p>
<p>The real fun resides in the <code>.SAJ</code> directory. If you are a little familiar with
MySQL you can now see that Sage 50 is using MySQL with InnoDB, which is great
news for us. I guess if you had time to spare, you could extract all the data
you need from there.</p>
<p>We are not going to do that though: I'm not familiar with accounting nor Sage 50,
and chances are neither are you.</p>
<h2>Changing the sysadmin password with the help of MySQL</h2>
<p>This part is greatly inspired by <a href="http://www.thegeekstuff.com/2014/04/recover-innodb-mysql/">this article</a>. Shout out to Santosh
Yadav! If you are not yet logged in as <code>root</code> on the Debian computer, please do
so. All the commands that follow need to run as superuser.</p>
<p>If you have not yet installed MySQL on your Debian computer, it's now time to do
it:</p>
<pre>
$ apt install mysql-server
</pre>
<p>Note that we are not using MariaDB even though it's a drop-in replacement for
Oracle's MySQL because:</p>
<ul>
<li>I did not test this with MariaDB</li>
<li>Sage 50 is likely using Oracle's MySQL and InnoDB can be a tricky thing</li>
</ul>
<p>Maybe this procedure indeed works with MariaDB, who knows? If you can't run
Oracle's MySQL for whatever reason but can run MariaDB, give it a try!</p>
<p>Anyway, what we will be doing is opening the <code>tuser</code> table and replacing the
sysadmin password by a new one. We can't just read the password from that table
since it is hashed with some proprietary algorithm. Since we don't know the
algorithm used, we cannot brute force the hash either.</p>
<p>I thus created a new Sage 50 database using <code>patate55</code> as the sysadmin password
and got this hash:</p>
<p><code>jt8UzeaVRSk/lzb1UCaBXw==</code></p>
<p>That's the hash we will use to replace the old password. After that, you will be
able to open your file using <code>sysadmin</code> as username and <code>patate55</code> as password.</p>
<p>The first step is to copy the files in the <code>.SAJ</code> directory to <code>/var/lib/mysql</code>:</p>
<pre>
$ service mysql stop
$ cp -R /path/to/the/SAJ/directory/* /var/lib/mysql
$ chown -R mysql:mysql /var/lib/mysql
</pre>
<p>You also need to modify the <code>/etc/mysql/my.cnf</code> to specify the size of the
<code>ib_logfile0</code> in the <code>.SAJ</code> directory:</p>
<pre>
$ echo 'innodb_log_file_size=2M' >> /etc/mysql/my.cnf
</pre>
<p>Once that is done, you can start MySQL again. Since we have overwritten some of
the previous data in the <code>/var/lib/mysql</code> directory, your MySQL root password
won't work anymore. You can fix that by restarting it this way:</p>
<pre>
$ mysqld_safe --skip-grant-tables &
</pre>
<p>You can now log in into MySQL:</p>
<pre>
$ mysql -u root
</pre>
<p>You should now see the <code>mysql ></code> prompt. Run these commands to display the
<code>tuser</code> table, the table that contains the user login infos:</p>
<pre>
> use simply;
> select * from tuser;
</pre>
<p>You should see something resembling this:</p>
<pre>
| lId | sName | nGLAccess | nPAAccess | nREAccess | nPRAccess | nINAccess | nPJAccess | n3rdParty | bAdmin | nTBAccess | nGJAccess | nPUJAccess | nPYJAccess | nSJAccess | nRJAccess | nPRJAccess | nIJAccess | bFullAcc | nLangPref | nUserType | sPassword | bExpired | lRole | nBRAccess | nDSAccess | sEmail |
+-----+-------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+--------+-----------+-----------+------------+------------+-----------+-----------+------------+-----------+----------+-----------+-----------+--------------------------+----------+-------+-----------+-----------+---------------------------+
| 1 | sysadmin | 7 | 7 | 7 | 7 | 7 | 7 | 2 | 1 | 7 | 7 | 7 | 7 | 7 | 7 | 7 | 6 | 1 | 2 | 0 | fd2DacqSFCk/lzb7UCfBXw== | 0 | 1 | 7 | 7 | sysadmin@foobar.com |
| 2 | User2 | 7 | 5 | 7 | 0 | 0 | 0 | 2 | 0 | 0 | 7 | 7 | 0 | 7 | 7 | 0 | 0 | 0 | 2 | 0 | pACbfSY1jthQj5c3CiHk2g== | 0 | 0 | 0 | 0 | user2@foobar.com |
+-----+-------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+--------+-----------+-----------+------------+------------+-----------+-----------+------------+-----------+----------+-----------+-----------+--------------------------+----------+-------+-----------+-----------+---------------------------+
</pre>
<p>Now comes the moment when we replace the old password hash with the new one. For
me the old sysadmin password hash is <code>fd2DacqSFCk/lzb7UCfBXw==</code>. Please find
that hash in the data the last command displayed on your screen and replace
<code>OLD_HASH</code> in the next command by it:</p>
<pre>
> update simply.tuser set sPassword = replace(sPassword,'OLD_HASH','jt8UzeaVRSk/lzb1UCaBXw==');
</pre>
<p>If everything went well, you should have replaced the old sysadmin password you
lost by <code>patate55</code>. You can verify this by running:</p>
<pre>
> select * from tuser;
</pre>
<p>You should now see a line like this:</p>
<pre>
| 1 | sysadmin | 7 | 7 | 7 | 7 | 7 | 7 | 2 | 1 | 7 | 7 | 7 | 7 | 7 | 7 | 7 | 6 | 1 | 2 | 0 | jt8UzeaVRSk/lzb1UCaBXw== | 0 | 1 | 7 | 7 | sysadmin@foobar.com |
</pre>
<p>You can now quit the MySQL prompt:</p>
<pre>
> exit
</pre>
<h2>Packing things back up</h2>
<p>The only thing left to do is to pack things back up and to move them back on the
Windows computer. First copy back the files from the MySQL directory to your
home directory:</p>
<pre>
$ mkdir ~/patate55.SAJ
$ cp -R /var/lib/mysql/* ~/patate55.SAJ/
</pre>
<p>You'll also need a <code>.SAI</code> file for Sage 50 to work properly:</p>
<pre>
$ cp /path/to/the/SAI/file ~/patate55.SAI
</pre>
<p>You can now copy the <code>patate55.SAJ</code> directory and the <code>patate55.SAI</code> file back
to your Windows computer and open it using <code>sysamin</code> and <code>patate55</code> during the
authentication prompt.</p>
<p>Chances are you saved a few days of work to someone. Entering a whole year (or
more!) of financial transactions by hand is no fun and it's even worse if you
have to do it a second time. Grab a beer or something, you deserved it.</p>