Recover Lost Sage 50 (Simply Accounting) Password with Free Software

2017-06-08 - Louis-Philippe Véronneau

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.

We switched to LibreOffice Calc for our accounting when I started working there, but the company used to use Sage 50.

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.

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!

Roll Safe meme: You can't forget your passwords if you never had any

I recommend using KeePass if you are using Windows and KeepassXC under Linux.

Anyway, back to the main topic: how the hell can one open a Sage 50 database when you lost the password?

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.

So yeah, please don't download these things and read on.

Prerequisites

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.

For that, you will need:

  • A Windows computer running Sage 50
  • A Debian computer
  • Some patience and a little familiarity with the command line

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.

Extracting the database

The file you are trying to open is likely an automatic backup copy Sage 50 saved somewhere. Those files are .CAB files, a type of lossless compression archive Windows uses.

Copy the .CAB file to your Debian computer. If the computer has a graphic interface, the easiest way to extract the archive is to open it with file-roller. If it is not installed by default, you can install it by running:

$ sudo apt install file-roller

On a headless computer, you will need to use cabextract.

Once you extracted the files, you should end up with something like this:

├── 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

So yeah, you end up with a very small file (the .SAI file) and one larger directory (the .SAJ directory).

The .SAI 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 .SAJ directory that has the same name the .SAI file has, so be sure to keep the two named the same way.

The real fun resides in the .SAJ 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.

We are not going to do that though: I'm not familiar with accounting nor Sage 50, and chances are neither are you.

Changing the sysadmin password with the help of MySQL

This part is greatly inspired by this article. Shout out to Santosh Yadav! If you are not yet logged in as root on the Debian computer, please do so. All the commands that follow need to run as superuser.

If you have not yet installed MySQL on your Debian computer, it's now time to do it:

$ apt install mysql-server

Note that we are not using MariaDB even though it's a drop-in replacement for Oracle's MySQL because:

  • I did not test this with MariaDB
  • Sage 50 is likely using Oracle's MySQL and InnoDB can be a tricky thing

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!

Anyway, what we will be doing is opening the tuser 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.

I thus created a new Sage 50 database using patate55 as the sysadmin password and got this hash:

jt8UzeaVRSk/lzb1UCaBXw==

That's the hash we will use to replace the old password. After that, you will be able to open your file using sysadmin as username and patate55 as password.

The first step is to copy the files in the .SAJ directory to /var/lib/mysql:

$ service mysql stop
$ cp -R /path/to/the/SAJ/directory/* /var/lib/mysql
$ chown -R mysql:mysql /var/lib/mysql

You also need to modify the /etc/mysql/my.cnf to specify the size of the ib_logfile0 in the .SAJ directory:

$ echo 'innodb_log_file_size=2M' >> /etc/mysql/my.cnf

Once that is done, you can start MySQL again. Since we have overwritten some of the previous data in the /var/lib/mysql directory, your MySQL root password won't work anymore. You can fix that by restarting it this way:

$ mysqld_safe --skip-grant-tables &

You can now log in into MySQL:

$ mysql -u root

You should now see the mysql > prompt. Run these commands to display the tuser table, the table that contains the user login infos:

> use simply;
> select * from tuser;

You should see something resembling this:

| 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 |
+-----+-------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+--------+-----------+-----------+------------+------------+-----------+-----------+------------+-----------+----------+-----------+-----------+--------------------------+----------+-------+-----------+-----------+---------------------------+

Now comes the moment when we replace the old password hash with the new one. For me the old sysadmin password hash is fd2DacqSFCk/lzb7UCfBXw==. Please find that hash in the data the last command displayed on your screen and replace OLD_HASH in the next command by it:

> update simply.tuser set sPassword = replace(sPassword,'OLD_HASH','jt8UzeaVRSk/lzb1UCaBXw==');

If everything went well, you should have replaced the old sysadmin password you lost by patate55. You can verify this by running:

> select * from tuser;

You should now see a line like this:

|   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 |

You can now quit the MySQL prompt:

> exit

Packing things back up

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:

$ mkdir ~/patate55.SAJ
$ cp -R /var/lib/mysql/* ~/patate55.SAJ/

You'll also need a .SAI file for Sage 50 to work properly:

$ cp /path/to/the/SAI/file ~/patate55.SAI

You can now copy the patate55.SAJ directory and the patate55.SAI file back to your Windows computer and open it using sysamin and patate55 during the authentication prompt.

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.


sage50passworddebian