User Tools

Site Tools




Preventing Piracy of Proprietary Add-Ons


Add “Get more features” button to SOFA.

Build web system.

Build first extensions.

SOFA needs to show where it is installer so extensions can be installed to the same place.


  • Want an easy purchase and installation experience for legitimate users which, even if it fails, leaves them able to use the community edition functionality of SOFA. It must be easy to install on multiple machines, and to keep upgraded.
  • Assumed impossible to prevent cracking unless requiring users to be online the whole time - rejected as too annoying for legitimate users.
  • Deceit should prevent true cracking from occurring - crackers will think there is a username and serial id available which works and move on. It will take over a month before anyone (probably) realises the crack doesn't work. Any new cracks etc will be competing with old information about cracks etc. The goal is to increase the fear, uncertainty and doubt of people considering using cracks. The more successful the fud experienced, the less piracy and the more legitimate sales. Sales revenue is the goal - not winning an arms race with crackers per se.

User Experience

Get to SOFA extension modules page, enter details e.g. username and log in, select purchases and discounts, get to payment page and make payment for extensions to purchase/increase download period, get a message, check inbox, download the extension module installer(s), install SOFA, install the SOFA extension(s), open SOFA, prompted for username and serial id on first use of any proprietary extension functionality. Only have to do once per extension module.


Mainly through obscurity in that if a cracker paid proper attention they would be able to supply users with something which never checked if it was registered or not. They could even control the display name. The plan is that crackers will never bother because they will assume they have a working username and serial id to share. And anyone else won't be able to work through the encryption, Python code etc.

The rest of the security system is really focused on preventing less technically sophisticated users from being able to easily bypass the anti-piracy e.g. by changing a text setting of 'unregistered' to 'registered'. No benefit in baking registration checking or nag checking code into binaries or anything - it will always surface in visible code somewhere e.g. when the code decides to either provide the functionality or display a nag message instead. It also means I can do this easily in Ubuntu and Linux as well as Windows and Mac.

The local text file controlling nagging/functionality shutdown will use a simple hash to obfuscate things.

Experience of Pirates

  1. If username and id for module don't match, specific functionality will not run and a nag will be shown instead.
  2. If extension module not considered purchased by user in SOFA web database, or username is considered cracked by the web database, SOFA schedules nagging and functionality shutdown for about a month.

Packaging Implications

Any proprietary extension modules will have responsibility for making the anti-piracy measures kick in by calling them from lib. The extension module will then decide what the nag message is (possibly using a boilerplate helper function from lib) and which of their own methods/functions check for registration and purchase. It doesn't matter if multiple functions check because it is made inexpensive by using session variables.

The nag dates stored would be by separated by proprietary module. Thus getting one module would not prevent nagging for other unregistered modules. functionality

Registration – a matching username and id are entered (for the relevant module). Stored locally. It doesn't matter whether the username is considered cracked or if there is no evidence of purchase. That is a separate issue because we want people to be able to use the extra functionality regardless (at least until the reminder system kicks in). If able to access SOFA web database, and registration_status is 'unreg', set to 'reg'. Function in SOFA will require matching API in web system:

update_web_reg_status(username, extension)
If registration_status on the SOFA web database is 'unreg', set it to 'reg'.

Purchase status – a registered and uncracked username matches a username (for the relevant module) in the purchased modules table on the web database. Purchase status is also stored locally. Function in SOFA will require matching API in web system:

has_web_rec_of_purchase(username, extension)
Returns purchased status for particular extension, and displayname (may not exist in which case returns empty string.  False if deemed cracked.

Anti-Piracy Phone Home Function in SOFA will require matching API in web system:

If no record of connections, add userid (yes - userid, not username) to list and set connection counter to 1. Otherwise, just increment.

Without registration, new functionality can't be used at all. The user will repeatedly be prompted to register each time they try and use the extra functionality. With registration, but not purchase, functionality can be used for a limited time. With registration and purchase, functionality can be used.

Check local records to see if this module is registered. Might as well check each time as fast enough and prevents parallel code.

If not registered, force a registration attempt. This happens every time an attempt is made to use the module.

If it has been registered, check local records to see if it has been purchased (if in purchased module list, True, if not, False).

If it has been recorded locally as being purchased, proceed.

If not, see if we have already tried to check for this module in the SOFA web database this session.

If we have, continue.

If we haven't, try to check the SOFA web database to see if it has been purchased (and username is not deemed cracked).

If not purchased, or if we can't access the SOFA web database, add module to list of modules to be nagged about. Start nagging etc in a month from now.

If it has been purchased, store in local record of purchased modules, wipe the nag date for that module, and store the username associated with that module as the username to use for SOFA for this user. NB if a user uses different usernames for different modules, the display name associated with the most recent username will override the rest. Or perhaps they have been permitted to update their display name. Whatever the reason, only one, if any, is stored and that is what is displayed. A legitimate user will never have anything to complain about.

OK - the appropriate nagging has been set for this module (added if unable to prove at some point, possibly in an earlier session, it was purchased and the username is not cracked; or removed if they have been able to prove at some point it was purchased). If not before the nag date, provide appropriate nag.

SOFA website functionality

Initial user messages

Prospective purchasers get to the get_extensions.php page from the SOFA home page or a button (e.g. Get More Features) on the application itself. This page describes the benefits e.g.:

  • exports data to spreadsheet
  • export report tables, charts, and entire reports as images
  • automated data backups for peace of mind
  • extra styles for report tables and charts
  • able to upgrade to latest version for 12 months

Pricing will be low: student discount $10, other $25. Users will be told they can purchase extensions or add a year of guaranteed free updates.

Logging in

The first step is the standard login arrangements everyone uses on websites. The user can login, or register as a user.

If registering as a new user, they need to enter a username and password. The username is checked to make sure it is not already in use. The first-time, registering user must supply display name (e.g. Dr John Smith), username (e.g. johnsmith), organisation (e.g. University of Birmingham), email address (e.g., permission to contact with SOFA offers etc, and a password (which will be salted, hashed, and stored).

Clients who are already registered can edit any details other than their username.The latter is immutable so that SOFA doesn't deem a product unregistered simply because a username has been changed by the user; and to make it easy to create valid extension download links using username. The same checks occur as when registering.

Making purchases

Once a client is logged in they can select the extensions they want to purchase or to upgrade AND whether any discount applies e.g. student/senior/hardship. Extensions already purchased will show the expiry date for free upgrades and the checkbox will be for adding a year of guaranteed free updates. NB extensions are not time limited but they may stop working with later versions of SOFA as it changes. But you can get newer versions for a full year (up to a limit of 5 downloads per operating system per CLIC version - make this clear to user). We don't want to make it hard for existing users to purchase more extensions or to extend upgrade durations.

There will also be a big fat “Buy Now” button. This will take them to a purchase page (VISA etc) with prices, display name etc will be transferred across from the previous form in a read-only format.

On successful purchase, if the user is new, the SOFA web database records the username in the users table. Other fields include userid, displayname, organisation, and email. The step of adding a user does not take place until at least one item has been purchased. This way we can be sure good usernames are not taken by non-customers.

CREATE TABLE `tblusers` (
`strUser` CHAR(30) COLLATE utf8_unicode_ci NOT NULL,
`strPwd_Checkstring` CHAR(60) COLLATE utf8_unicode_ci NOT NULL,
`displayname` CHAR(80) COLLATE utf8_unicode_ci NOT NULL,
`organisation` CHAR(80) COLLATE utf8_unicode_ci DEFAULT NULL,
`email` CHAR(80) COLLATE utf8_unicode_ci NOT NULL,
`email_opt_in` TINYINT(1) NOT NULL DEFAULT '0',
`intPriv_ID` INT(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`intUser_ID`)

There will also be a table for recording extension module purchases per user. It will have the userid for linking, a generated serial id which is consistent with the module name and the username but cannot be derived from them, download_expiry_date, and a registration_status field ('unreg' (default), 'reg', 'cracked') which can be manually set by me, typically in response to a warning report.

CREATE TABLE `tblpurchases` (
`intUser_ID` INT(11) NOT NULL,
`extensionid` INT(11) NOT NULL,
`serialid` CHAR(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`download_expiry_date` DATE NOT NULL,
`registration_status` CHAR(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'unreg',
PRIMARY KEY (`purchaseid`)

In the SOFA web database here will also be a table for recording downloads - it will have downloadid, usermoduleid, version, and date fields. This can be used to prevent excessive downloads per paid username e.g. if the download links are passed around to non-paying users. This adds a modest barrier to piracy by decreasing convenience for pirates. If they sidestep the legitimate links then they can't be as sure the files they download are safe.

There will also be a table to record connections per userid (submits username, gets userid, stores userid and increments connect_count by 1. This can help identify piracy by showing if there is excessive usage for a given userid. These userid can then be tagged by me as cracked which will impact on those users (regular nag screen/functionality shutdown) a month or so after they make their first connection to the SOFA server. NB uses userid rather than username in case someone changes that every-so-often.

Message sent to user

Having made the purchase, the user will be informed an email has been sent to the email address they supplied. They will be warned to check their junk folder etc if they can't find it. In the email it will say the appropriate of the following depending on what has been purchased:

Congratulations for your purchase of the following extension module(s) for SOFA Statistics:

Congratulations for increasing the new download period for the following extension module(s) for SOFA Statistics:

Congratulations for your purchase of the following extension module(s) for SOFA Statistics: ... and for increasing the new download period for the following extension module(s): ...

You are now able to download the SOFA extension module installers till the following date(s):

mod #1 - download period ends ...

Your username is johnsmith1 and your serial number is abc1234. Please keep this email safe or print it for future reference.

The email will also include 4 links for each extension module (Win, Mac, Ubuntu, Other) - each of which will enable them to download the extension module installers until the expiry date for that module. They are allowed to download 5 times per version (e.g. 5 times for version 1.1.4). The links will include the username and serial id which will be checked by the SOFA web database. Successful downloads will be recorded in the downloads table.

Installation of extension module(s)

The user downloads the installer they need (which will be recorded in the downloads table on the SOFA web database) and run the installer. SOFA will have to be installed already. Assuming it is installed, users will need to know where it is installed and install the extension to the same place. SOFA will reveal where it is installed. Users will be prompted to open the internet if possible (so that SOFA can keep them informed about new versions available). The username and id are entered when prompted during the first use of a particular module in SOFA e.g. clicking on new buttons added. These must be consistent with each other. If not, the button click or whatever won't do anything apart from triggering a nag message. If they match, the details are stored in an encrypted fashion locally ready for use when connecting to the SOFA web server. If there is a connection, the display name is also taken from the SOFA web database and stored ready for SOFA to use when opening the main form. If SOFA can't connect, then SOFA stores locally a date (associated with specific module name) for nagging/functionality shutdown to commence. This date is wiped if the system is registered successfully. If SOFA can connect, it submits the username and serial id to the server. If they are consistent, and registration_status on the SOFA web database is 'unreg', it is set to 'reg' and any local nag date is wiped. If, however, the web database deems the username 'cracked', the local nag date is set. The user never realises the cracked username and serial id failed in any way.

Crack check

NB every time the user opens SOFA and is connected to the internet it will check to see if they are deemed cracked. If they are, all local records of extensions as being purchased will be wiped. This will automatically trigger the following: if there is not already a nag date stored, or the nag date is more than a month away, SOFA will locally update the nag date. And whether or not the internet is connected, SOFA will show the nag screen and shutdown unpurchased functionality if the nag date has passed. The nag message will not be nasty but will let the user know that the system is not successfully registered. It will advise them to register using their username and serial id with the internet connected. If they are unable to connect successfully outside, they should email for assistance.


set2reg(username, extension)

is_purchased(username, extension)



proj/antipiracy.txt · Last modified: 2012/03/30 00:57 (external edit)